Skip to content

Commit d97f37d

Browse files
author
doujiang24
committed
bugfix: out-of-bounds memory writing may happen in chash_point_sort. openresty#41
1 parent 56fd8ad commit d97f37d

File tree

3 files changed

+82
-8
lines changed

3 files changed

+82
-8
lines changed

.travis.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,52 @@ addons:
2121
- liburi-perl
2222
- libwww-perl
2323
- perl
24+
- valgrind
2425

2526
cache:
2627
directories:
2728
- download-cache
2829

2930
env:
3031
global:
31-
- JOBS=2
32-
- OPENRESTY_PREFIX=/usr/local/openresty
33-
- OPENRESTY_VER=1.11.2.3
32+
- JOBS=2
33+
- OPENRESTY_PREFIX=/usr/local/openresty
34+
- OPENRESTY_VER=1.19.9.1
35+
jobs:
36+
- TEST_NGINX_USE_VALGRIND=0
37+
- TEST_NGINX_USE_VALGRIND=1
3438

3539
install:
3640
- if [ ! -f download-cache/openresty-$OPENRESTY_VER.tar.gz ]; then
3741
wget -P download-cache https://openresty.org/download/openresty-$OPENRESTY_VER.tar.gz;
3842
fi
3943
- git clone https://github.com/openresty/test-nginx.git ../test-nginx
4044

45+
# install openresty-openssl111-dev
46+
- sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates
47+
- wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
48+
- echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
49+
| sudo tee /etc/apt/sources.list.d/openresty.list
50+
- sudo apt-get update || echo 'apt-get update failed, but ignore it'
51+
- sudo apt-get -y install --no-install-recommends openresty-openssl111 openresty-openssl111-dev
52+
4153
script:
54+
- if [ TEST_NGINX_USE_VALGRIND = 1 ]; then export luajit_xcflags='-DLUAJIT_USE_VALGRIND -DLUAJIT_USE_SYSMALLOC'; fi
4255
- tar xzf download-cache/openresty-$OPENRESTY_VER.tar.gz &&
4356
cd openresty-$OPENRESTY_VER
44-
- ./configure --prefix=$OPENRESTY_PREFIX -j$JOBS
45-
> build.log 2>&1 || (cat build.log && exit 1)
57+
- ./configure --prefix=$OPENRESTY_PREFIX
58+
--with-cc-opt="-I/usr/local/openresty/openssl111/include"
59+
--with-ld-opt="-L/usr/local/openresty/openssl111/lib -Wl,-rpath,/usr/local/openresty/openssl111/lib"
60+
--with-luajit-xcflags="$luajit_xcflags"
61+
-j$JOBS
62+
> build.log 2>&1 || (cat build.log && exit 1)
4663
- make -j$JOBS > build.log 2>&1 ||
4764
(cat build.log && exit 1)
4865
- sudo make install > build.log 2>&1 ||
4966
(cat build.log && exit 1)
5067
- cd ..
5168
- export PATH=$OPENRESTY_PREFIX/nginx/sbin:$PATH
52-
- make test jobs=$JOBS
69+
- make test jobs=$JOBS > build.log 2>&1 ||
70+
(cat build.log && exit 1)
71+
- cat build.log
72+
- if [ `grep -c '== Invalid' build.log` -gt 0 ]; then echo 'valgrind complaining' && exit 1; fi

chash.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33
#include <math.h>
4+
#include <assert.h>
5+
46
#include "chash.h"
57

68

@@ -164,7 +166,9 @@ chash_point_sort(chash_point_t arr[], uint32_t n)
164166

165167
for (i = 0; i < n; i++) {
166168
node = &arr[i];
167-
index = node->hash / step; // can not bigger than m
169+
index = node->hash / step;
170+
171+
assert(index < m); // index must less than m
168172

169173
for (end = index; end >= 0; end--) {
170174
if (points[end].id == 0) {
@@ -188,7 +192,10 @@ chash_point_sort(chash_point_t arr[], uint32_t n)
188192

189193
/* left shift after end when node->hash is bigger than them */
190194
/* only end == index can match this */
191-
while (points[end + 1].id != 0 && points[end + 1].hash < node->hash) {
195+
while (end + 1 < m
196+
&& points[end + 1].id != 0
197+
&& points[end + 1].hash < node->hash)
198+
{
192199
points[end].hash = points[end + 1].hash;
193200
points[end].id = points[end + 1].id;
194201
end += 1;
@@ -223,6 +230,8 @@ chash_point_sort(chash_point_t arr[], uint32_t n)
223230
}
224231

225232
insert:
233+
assert(end < m && end >= 0);
234+
226235
points[end].id = node->id;
227236
points[end].hash = node->hash;
228237
}

t/chash.t

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,48 @@ size: 480
356356
--- no_error_log
357357
[error]
358358
--- timeout: 30
359+
360+
361+
362+
=== TEST 6: random key fuzzer
363+
--- http_config eval: $::HttpConfig
364+
--- config
365+
location /t {
366+
content_by_lua_block {
367+
math.randomseed(ngx.now())
368+
369+
local ffi = require "ffi"
370+
local resty_chash = require "resty.chash"
371+
372+
local function random_string()
373+
local len = math.random(10, 100)
374+
local buf = ffi.new("char [?]", len)
375+
for i = 0, len - 1 do
376+
buf[i] = math.random(0, 255)
377+
end
378+
379+
return ffi.string(buf, len)
380+
end
381+
382+
for i = 1, 30 do
383+
local servers = {}
384+
385+
local len = math.random(1, 100)
386+
for j = 1, len do
387+
local key = random_string()
388+
servers[key] = math.random(1, 100)
389+
end
390+
391+
local chash = resty_chash:new(servers)
392+
end
393+
394+
ngx.say("done")
395+
}
396+
}
397+
--- request
398+
GET /t
399+
--- response_body
400+
done
401+
--- no_error_log
402+
[error]
403+
--- timeout: 30

0 commit comments

Comments
 (0)