<HTML><BODY><div>Hi, Sergey!</div><div>Thanks for the patch!</div><div>LGTM</div><div> </div><div data-signature-widget="container"><div data-signature-widget="content"><div>--<br>Best regards,</div><div>Maxim Kokryashkin</div></div></div><div> </div><div> </div><blockquote style="border-left:1px solid #0857A6; margin:10px; padding:0 0 0 10px;">Вторник, 21 ноября 2023, 11:57 +03:00 от Sergey Kaplun <skaplun@tarantool.org>:<br> <div id=""><div class="js-helper js-readmsg-msg"><div><div id="style_17005570471274232613_BODY">From: Mike Pall <mike><br><br>Reported by XmiliaH.<br><br>(cherry-picked from commit e56048753634c32ea6eeedf74cef6f9cfea5f4ed)<br><br>When parsing exponent powers greater than (1 << 16) * 10 == (65536 *<br>10), the exponent values are cut without handling any values greater.<br>This patch fixes the behaviour, but restricts the power maximum value by<br>`STRSCAN_MAXEXP` (1 << 20).<br><br>Sergey Kaplun:<br>* added the description and the test for the problem<br><br>Part of tarantool/tarantool#9145<br>---<br><br>Branch:<br><a href="https://github.com/tarantool/luajit/tree/skaplun/lj-788-limit-exponents-range" target="_blank">https://github.com/tarantool/luajit/tree/skaplun/lj-788-limit-exponents-range</a><br>Tarantool PR: <a href="https://github.com/tarantool/tarantool/pull/9386" target="_blank">https://github.com/tarantool/tarantool/pull/9386</a><br>Related issues:<br>* <a href="https://github.com/LuaJIT/LuaJIT/issues/788" target="_blank">https://github.com/LuaJIT/LuaJIT/issues/788</a><br>* <a href="https://github.com/tarantool/tarantool/issues/9145" target="_blank">https://github.com/tarantool/tarantool/issues/9145</a><br><br><br> src/lj_strscan.c | 5 +++-<br> .../lj-788-limit-exponents-range.test.lua | 29 +++++++++++++++++++<br> 2 files changed, 33 insertions(+), 1 deletion(-)<br> create mode 100644 test/tarantool-tests/lj-788-limit-exponents-range.test.lua<br><br>diff --git a/src/lj_strscan.c b/src/lj_strscan.c<br>index ae8945e1..129010fd 100644<br>--- a/src/lj_strscan.c<br>+++ b/src/lj_strscan.c<br>@@ -63,6 +63,7 @@<br> #define STRSCAN_MAXDIG 800 /* 772 + extra are sufficient. */<br> #define STRSCAN_DDIG (STRSCAN_DIG/2)<br> #define STRSCAN_DMASK (STRSCAN_DDIG-1)<br>+#define STRSCAN_MAXEXP (1 << 20)<br> <br> /* Helpers for circular buffer. */<br> #define DNEXT(a) (((a)+1) & STRSCAN_DMASK)<br>@@ -449,6 +450,7 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,<br> if (dig) {<br> ex = (int32_t)(dp-(p-1)); dp = p-1;<br> while (ex < 0 && *dp-- == '0') ex++, dig--; /* Skip trailing zeros. */<br>+ if (ex <= -STRSCAN_MAXEXP) return STRSCAN_ERROR;<br> if (base == 16) ex *= 4;<br> }<br> }<br>@@ -462,7 +464,8 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,<br> if (!lj_char_isdigit(*p)) return STRSCAN_ERROR;<br> xx = (*p++ & 15);<br> while (lj_char_isdigit(*p)) {<br>- if (xx < 65536) xx = xx * 10 + (*p & 15);<br>+ xx = xx * 10 + (*p & 15);<br>+ if (xx >= STRSCAN_MAXEXP) return STRSCAN_ERROR;<br> p++;<br> }<br> ex += negx ? -(int32_t)xx : (int32_t)xx;<br>diff --git a/test/tarantool-tests/lj-788-limit-exponents-range.test.lua b/test/tarantool-tests/lj-788-limit-exponents-range.test.lua<br>new file mode 100644<br>index 00000000..8ab31600<br>--- /dev/null<br>+++ b/test/tarantool-tests/lj-788-limit-exponents-range.test.lua<br>@@ -0,0 +1,29 @@<br>+local tap = require('tap')<br>+<br>+-- Test file to demonstrate incorrect behaviour of exponent number<br>+-- form parsing.<br>+-- See also: <a href="https://github.com/LuaJIT/LuaJIT/issues/788" target="_blank">https://github.com/LuaJIT/LuaJIT/issues/788</a>.<br>+local test = tap.test('lj-788-limit-exponents-range')<br>+test:plan(2)<br>+<br>+-- Before the patch, the powers greater than (1 << 16) * 10<br>+-- (655360) were parsed incorrectly. After the patch, powers<br>+-- greater than 1 << 20 (1048576 `STRSCAN_MAXEXP`) are considered<br>+-- invalid. See <src/lj_strscan.c> for details.<br>+-- Choose the first value between these values and the second<br>+-- value bigger than `STRSCAN_MAXEXP` to check parsing correctness<br>+-- for the first one, and `STRSCAN_ERROR` for the second case.<br>+local PARSABLE_EXP_POWER = 1000000<br>+local TOO_LARGE_EXP_POWER = 1050000<br>+<br>+local function form_exp_string(n)<br>+ return '0.' .. string.rep('0', n - 1) .. '1e' .. tostring(n)<br>+end<br>+<br>+test:is(tonumber(form_exp_string(PARSABLE_EXP_POWER)), 1,<br>+ 'correct parsing of large exponent')<br>+<br>+test:is(tonumber(form_exp_string(TOO_LARGE_EXP_POWER)), nil,<br>+ 'too big exponent power is not parsed')<br>+<br>+test:done(true)<br>--<br>2.42.1</div></div></div></div></blockquote><div> </div></BODY></HTML>