diff options
| author | Thijs Schreijer <thijs@thijsschreijer.nl> | 2026-08-29 17:09:47 +0200 |
|---|---|---|
| committer | Thijs Schreijer <thijs@thijsschreijer.nl> | 2026-08-29 17:22:29 +0200 |
| commit | 8cbbce56e64c84b53593c815f6dcdd9214897b74 (patch) | |
| tree | 101db7e5d326b8e7b8394840dda6d4de6eec343a | |
| parent | e912d157b242e661dca37d0a8269202dda974ba7 (diff) | |
| download | luasocket-8cbbce56e64c84b53593c815f6dcdd9214897b74.tar.gz luasocket-8cbbce56e64c84b53593c815f6dcdd9214897b74.tar.bz2 luasocket-8cbbce56e64c84b53593c815f6dcdd9214897b74.zip | |
fix(receive): guard maxsize against size_t overflow on cast
Casting a double larger than SIZE_MAX to size_t is undefined
behavior; bound-check maxsize before the cast.
| -rw-r--r-- | src/buffer.c | 3 | ||||
| -rw-r--r-- | test/testclnt.lua | 6 |
2 files changed, 6 insertions, 3 deletions
diff --git a/src/buffer.c b/src/buffer.c index 05d6fb3..5f06fc1 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -134,7 +134,8 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) { | |||
| 134 | } | 134 | } |
| 135 | if (!lua_isnoneornil(L, 4)) { | 135 | if (!lua_isnoneornil(L, 4)) { |
| 136 | double m = luaL_checknumber(L, 4); | 136 | double m = luaL_checknumber(L, 4); |
| 137 | luaL_argcheck(L, m >= 1, 4, "maxsize must be a positive number"); | 137 | luaL_argcheck(L, m >= 1 && m < (lua_Number) ((size_t) -1), 4, |
| 138 | "maxsize must be a positive number"); | ||
| 138 | maxsize = (size_t) m; | 139 | maxsize = (size_t) m; |
| 139 | luaL_argcheck(L, size < maxsize, 4, | 140 | luaL_argcheck(L, size < maxsize, 4, |
| 140 | "prefix length >= maxsize (drain with prefix=\"\" or raise maxsize)"); | 141 | "prefix length >= maxsize (drain with prefix=\"\" or raise maxsize)"); |
diff --git a/test/testclnt.lua b/test/testclnt.lua index 3e897c9..ec154ea 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua | |||
| @@ -640,14 +640,16 @@ function test_maxsize() | |||
| 640 | assert(not ok, "A5 failed: #prefix > maxsize should raise") | 640 | assert(not ok, "A5 failed: #prefix > maxsize should raise") |
| 641 | ok = pcall(data.receive, data, 100, nil, 50) | 641 | ok = pcall(data.receive, data, 100, nil, 50) |
| 642 | assert(not ok, "A6 failed: wanted > maxsize should raise") | 642 | assert(not ok, "A6 failed: wanted > maxsize should raise") |
| 643 | ok = pcall(data.receive, data, "*l", nil, math.huge) | ||
| 644 | assert(not ok, "A7 failed: maxsize=math.huge should raise (size_t overflow)") | ||
| 643 | data:settimeout(0.1) | 645 | data:settimeout(0.1) |
| 644 | ok = pcall(data.receive, data, 50, nil, 100) | 646 | ok = pcall(data.receive, data, 50, nil, 100) |
| 645 | assert(ok, "A7 failed: wanted <= maxsize should not raise") | 647 | assert(ok, "A8 failed: wanted <= maxsize should not raise") |
| 646 | data:settimeout(-1) | 648 | data:settimeout(-1) |
| 647 | remote [[ data:send('intact\n') ]] | 649 | remote [[ data:send('intact\n') ]] |
| 648 | local line, err = data:receive("*l", nil, 100) | 650 | local line, err = data:receive("*l", nil, 100) |
| 649 | assert(line == "intact", | 651 | assert(line == "intact", |
| 650 | "A8 failed: socket touched by a failed argcheck (err=" .. | 652 | "A9 failed: socket touched by a failed argcheck (err=" .. |
| 651 | tostring(err) .. ")") | 653 | tostring(err) .. ")") |
| 652 | pass("ok") | 654 | pass("ok") |
| 653 | 655 | ||
