time_t mtime;
size_t size, len;
ssize_t n;
- uint32_t crc32;
ngx_err_t err;
ngx_int_t rc;
ngx_uint_t i;
goto failed;
}
- ngx_crc32_init(crc32);
+ /*
+ * the base is walked below without bounds checking, so make sure
+ * it is intact first: the checksum in the header is computed over
+ * the entire body, which the walk covers contiguously
+ */
+
+ if (size < sizeof(ngx_http_geo_header_t)
+ + sizeof(ngx_http_variable_value_t)
+ + 0x10000 * sizeof(ngx_http_geo_range_t *))
+ {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "truncated binary geo range base \"%s\"",
+ name->data);
+ goto failed;
+ }
+
+ if (ngx_crc32_long(base + sizeof(ngx_http_geo_header_t),
+ size - sizeof(ngx_http_geo_header_t))
+ != header->crc32)
+ {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "CRC32 mismatch in binary geo range base \"%s\"",
+ name->data);
+ goto failed;
+ }
vv = (ngx_http_variable_value_t *) (base + sizeof(ngx_http_geo_header_t));
while (vv->data) {
len = ngx_align(sizeof(ngx_http_variable_value_t) + vv->len,
sizeof(void *));
- ngx_crc32_update(&crc32, (u_char *) vv, len);
vv->data += (size_t) base;
vv = (ngx_http_variable_value_t *) ((u_char *) vv + len);
}
- ngx_crc32_update(&crc32, (u_char *) vv, sizeof(ngx_http_variable_value_t));
vv++;
ranges = (ngx_http_geo_range_t **) vv;
for (i = 0; i < 0x10000; i++) {
- ngx_crc32_update(&crc32, (u_char *) &ranges[i], sizeof(void *));
if (ranges[i]) {
ranges[i] = (ngx_http_geo_range_t *)
((u_char *) ranges[i] + (size_t) base);
while ((u_char *) range < base + size) {
while (range->value) {
- ngx_crc32_update(&crc32, (u_char *) range,
- sizeof(ngx_http_geo_range_t));
range->value = (ngx_http_variable_value_t *)
((u_char *) range->value + (size_t) base);
range++;
}
- ngx_crc32_update(&crc32, (u_char *) range, sizeof(void *));
range = (ngx_http_geo_range_t *) ((u_char *) range + sizeof(void *));
}
- ngx_crc32_final(crc32);
-
- if (crc32 != header->crc32) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "CRC32 mismatch in binary geo range base \"%s\"", name->data);
- goto failed;
- }
-
ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0,
"using binary geo range base \"%s\"", name->data);
time_t mtime;
size_t size, len;
ssize_t n;
- uint32_t crc32;
ngx_err_t err;
ngx_int_t rc;
ngx_uint_t i;
goto failed;
}
- ngx_crc32_init(crc32);
+ /*
+ * the base is walked below without bounds checking, so make sure
+ * it is intact first: the checksum in the header is computed over
+ * the entire body, which the walk covers contiguously
+ */
+
+ if (size < sizeof(ngx_stream_geo_header_t)
+ + sizeof(ngx_stream_variable_value_t)
+ + 0x10000 * sizeof(ngx_stream_geo_range_t *))
+ {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "truncated binary geo range base \"%s\"",
+ name->data);
+ goto failed;
+ }
+
+ if (ngx_crc32_long(base + sizeof(ngx_stream_geo_header_t),
+ size - sizeof(ngx_stream_geo_header_t))
+ != header->crc32)
+ {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "CRC32 mismatch in binary geo range base \"%s\"",
+ name->data);
+ goto failed;
+ }
vv = (ngx_stream_variable_value_t *)
(base + sizeof(ngx_stream_geo_header_t));
while (vv->data) {
len = ngx_align(sizeof(ngx_stream_variable_value_t) + vv->len,
sizeof(void *));
- ngx_crc32_update(&crc32, (u_char *) vv, len);
vv->data += (size_t) base;
vv = (ngx_stream_variable_value_t *) ((u_char *) vv + len);
}
- ngx_crc32_update(&crc32, (u_char *) vv,
- sizeof(ngx_stream_variable_value_t));
vv++;
ranges = (ngx_stream_geo_range_t **) vv;
for (i = 0; i < 0x10000; i++) {
- ngx_crc32_update(&crc32, (u_char *) &ranges[i], sizeof(void *));
if (ranges[i]) {
ranges[i] = (ngx_stream_geo_range_t *)
((u_char *) ranges[i] + (size_t) base);
while ((u_char *) range < base + size) {
while (range->value) {
- ngx_crc32_update(&crc32, (u_char *) range,
- sizeof(ngx_stream_geo_range_t));
range->value = (ngx_stream_variable_value_t *)
((u_char *) range->value + (size_t) base);
range++;
}
- ngx_crc32_update(&crc32, (u_char *) range, sizeof(void *));
range = (ngx_stream_geo_range_t *) ((u_char *) range + sizeof(void *));
}
- ngx_crc32_final(crc32);
-
- if (crc32 != header->crc32) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "CRC32 mismatch in binary geo range base \"%s\"", name->data);
- goto failed;
- }
-
ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0,
"using binary geo range base \"%s\"", name->data);