diff --git a/iocore/cache/Cache.cc b/iocore/cache/Cache.cc index 22b502aac89..ca5fcc60966 100644 --- a/iocore/cache/Cache.cc +++ b/iocore/cache/Cache.cc @@ -3089,6 +3089,7 @@ register_cache_stats(RecRawStatBlock *rsb, const char *prefix) REG_INT("read.success", cache_read_success_stat); REG_INT("read.failure", cache_read_failure_stat); REG_INT("read.seek.failure", cache_read_seek_fail_stat); + REG_INT("read.invalid", cache_read_invalid_stat); REG_INT("write.active", cache_write_active_stat); REG_INT("write.success", cache_write_success_stat); REG_INT("write.failure", cache_write_failure_stat); diff --git a/iocore/cache/CacheRead.cc b/iocore/cache/CacheRead.cc index 4c33cdf5d26..9d9f2452b26 100644 --- a/iocore/cache/CacheRead.cc +++ b/iocore/cache/CacheRead.cc @@ -1175,6 +1175,20 @@ CacheVC::openReadStartHead(int event, Event *e) } else { f.single_fragment = false; } + + // Now that we have selected an alternate, validate that the content length and object size match + MIMEField *field = alternate.response_get()->field_find(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH); + if (field) { + uint64_t cl = static_cast(field->value_get_int64()); + if (cl != doc_len) { + Warning("OpenReadHead failed for cachekey %X : alternate content length doesn't match doc_len %ld != %ld", key.slice32(0), + cl, doc_len); + CACHE_INCREMENT_DYN_STAT(cache_read_invalid_stat); + err = ECACHE_BAD_META_DATA; + goto Ldone; + } + } + } else { next_CacheKey(&key, &doc->key); f.single_fragment = doc->single_fragment(); diff --git a/iocore/cache/P_CacheInternal.h b/iocore/cache/P_CacheInternal.h index cf747de60cf..2d7a8cb8432 100644 --- a/iocore/cache/P_CacheInternal.h +++ b/iocore/cache/P_CacheInternal.h @@ -114,6 +114,7 @@ enum { cache_read_success_stat, cache_read_failure_stat, cache_read_seek_fail_stat, + cache_read_invalid_stat, cache_write_active_stat, cache_write_success_stat, cache_write_failure_stat,