Klaus Demo nginx / 5516407
Core: fixed segfault with too large bucket sizes (ticket #1806). To save memory hash code uses u_short to store resulting bucket sizes, so maximum bucket size is limited to 65536 minus ngx_cacheline_size (larger values will be aligned to 65536 which will overflow u_short). However, there were no checks to enforce this, and using larger bucket sizes resulted in overflows and segmentation faults. Appropriate safety checks to enforce this added to ngx_hash_init(). Maxim Dounin 1 year, 6 months ago
1 changed file(s) with 27 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
264264 return NGX_ERROR;
265265 }
266266
267 if (hinit->bucket_size > 65536 - ngx_cacheline_size) {
268 ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
269 "could not build %s, too large "
270 "%s_bucket_size: %i",
271 hinit->name, hinit->name, hinit->bucket_size);
272 return NGX_ERROR;
273 }
274
267275 for (n = 0; n < nelts; n++) {
268276 if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
269277 {
299307 }
300308
301309 key = names[n].key_hash % size;
302 test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
310 len = test[key] + NGX_HASH_ELT_SIZE(&names[n]);
303311
304312 #if 0
305313 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
306 "%ui: %ui %ui \"%V\"",
307 size, key, test[key], &names[n].key);
308 #endif
309
310 if (test[key] > (u_short) bucket_size) {
314 "%ui: %ui %uz \"%V\"",
315 size, key, len, &names[n].key);
316 #endif
317
318 if (len > bucket_size) {
311319 goto next;
312320 }
321
322 test[key] = (u_short) len;
313323 }
314324
315325 goto found;
340350 }
341351
342352 key = names[n].key_hash % size;
343 test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
353 len = test[key] + NGX_HASH_ELT_SIZE(&names[n]);
354
355 if (len > 65536 - ngx_cacheline_size) {
356 ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
357 "could not build %s, you should "
358 "increase %s_max_size: %i",
359 hinit->name, hinit->name, hinit->max_size);
360 return NGX_ERROR;
361 }
362
363 test[key] = (u_short) len;
344364 }
345365
346366 len = 0;