WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
187042
RegExp.exec returns wrong value with a long integer quantifier
https://bugs.webkit.org/show_bug.cgi?id=187042
Summary
RegExp.exec returns wrong value with a long integer quantifier
Thyago Pessoa
Reported
2018-06-26 07:27:47 PDT
Hi everyone, I found an inconsistence on Regexp pattern with a long integer quantifier. version: Safari-606.1.9.4 OS: Ubuntu 16.04 x64 Step to reproduce: r = new RegExp ("(?:a{0,34028236692}?){0,1}a"); // length 11 print(r.exec ("aa") == "aa"); // returns aa r = new RegExp ("(?:a{0,340282366920}?){0,1}a"); // length 12 print(r.exec ("aa") == "aa"); // returns a Actual results: true false Expected results: true true V8, Chakra and SpiderMonkey works as expected.
Attachments
Patch
(4.75 KB, patch)
2018-07-01 02:54 PDT
,
Sukolsak Sakshuwong
no flags
Details
Formatted Diff
Diff
Fix tests
(7.07 KB, patch)
2018-07-01 08:45 PDT
,
Sukolsak Sakshuwong
no flags
Details
Formatted Diff
Diff
Use Checked<unsigned, RecordOverflow> and quantifyInfinite
(7.07 KB, patch)
2018-07-01 09:47 PDT
,
Sukolsak Sakshuwong
no flags
Details
Formatted Diff
Diff
Forgot to update ChangeLog
(7.10 KB, patch)
2018-07-01 10:11 PDT
,
Sukolsak Sakshuwong
no flags
Details
Formatted Diff
Diff
Remove the extra overflow loop, use consumeDigit, and update ChangeLog
(6.93 KB, patch)
2018-07-01 14:41 PDT
,
Sukolsak Sakshuwong
no flags
Details
Formatted Diff
Diff
Patch for landing
(7.20 KB, patch)
2018-07-02 17:07 PDT
,
Sukolsak Sakshuwong
no flags
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
Sukolsak Sakshuwong
Comment 1
2018-07-01 02:54:26 PDT
Created
attachment 344045
[details]
Patch
EWS Watchlist
Comment 2
2018-07-01 04:14:18 PDT
Comment on
attachment 344045
[details]
Patch
Attachment 344045
[details]
did not pass jsc-ews (mac): Output:
https://webkit-queues.webkit.org/results/8402596
New failing tests: stress/regress-159744.js.ftl-no-cjit-no-inline-validate stress/regress-159744.js.dfg-eager-no-cjit-validate stress/regress-159744.js.no-cjit-validate-phases stress/regress-159744.js.dfg-eager stress/regress-159744.js.ftl-no-cjit-no-put-stack-validate stress/regress-159744.js.no-ftl stress/regress-159744.js.ftl-no-cjit-b3o1 stress/regress-159744.js.no-cjit-collect-continuously stress/regress-159744.js.ftl-eager-no-cjit-b3o1 stress/regress-159744.js.ftl-eager stress/regress-159744.js.no-llint stress/regress-159744.js.ftl-no-cjit-validate-sampling-profiler stress/regress-159744.js.ftl-eager-no-cjit stress/regress-159744.js.ftl-no-cjit-small-pool stress/regress-159744.js.default stress/regress-159744.js.dfg-maximal-flush-validate-no-cjit apiTests
Mark Lam
Comment 3
2018-07-01 07:57:24 PDT
Comment on
attachment 344045
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=344045&action=review
r- because a JSC test is failing. Please investigate as to why it's failing.
> Source/JavaScriptCore/yarr/YarrParser.h:990 > - // check for overflow. > - for (unsigned newValue; peekIsDigit() && ((newValue = n * 10 + peekDigit()) >= n); ) { > - n = newValue; > + while (peekIsDigit()) { > + unsigned nextDigit = peekDigit(); > + if (n > (UINT_MAX - nextDigit) / 10) { > + // Overflow. Skip past remaining decimal digits and return UINT_MAX. > + do { > + consume(); > + } while (peekIsDigit()); > + return UINT_MAX; > + } > + n = n * 10 + nextDigit; > consume(); > } > return n;
Please look into using Checked<unsigned, RecordOverflow> (grep for other places where this is used to see how it's used). You should use that here instead. It will simplify this code tremendously. Also, to be consistent with the rest of Yarr code, you should return quantifyInfinite here instead of UINT_MAX directly.
Sukolsak Sakshuwong
Comment 4
2018-07-01 08:45:02 PDT
Created
attachment 344050
[details]
Fix tests
Saam Barati
Comment 5
2018-07-01 09:38:25 PDT
Comment on
attachment 344050
[details]
Fix tests View in context:
https://bugs.webkit.org/attachment.cgi?id=344050&action=review
> Source/JavaScriptCore/yarr/YarrParser.h:987 > + n = n * 10 + nextDigit;
Let’s just use Checked<unsigned> for n
Saam Barati
Comment 6
2018-07-01 09:39:49 PDT
Comment on
attachment 344050
[details]
Fix tests View in context:
https://bugs.webkit.org/attachment.cgi?id=344050&action=review
>> Source/JavaScriptCore/yarr/YarrParser.h:987 >> + n = n * 10 + nextDigit; > > Let’s just use Checked<unsigned> for n
We can then return UINT_MAX if that overflows
Mark Lam
Comment 7
2018-07-01 09:43:13 PDT
Comment on
attachment 344050
[details]
Fix tests View in context:
https://bugs.webkit.org/attachment.cgi?id=344050&action=review
>>> Source/JavaScriptCore/yarr/YarrParser.h:987 >>> + n = n * 10 + nextDigit; >> >> Let’s just use Checked<unsigned> for n > > We can then return UINT_MAX if that overflows
I pointed this out earlier (in
https://bugs.webkit.org/show_bug.cgi?id=187042#c3
): use Checked<unsigned, RecordOverflow >. Plain Checked<unsigned> will crash on overflow, and I think we don't want that. Also, use quantifyInfinite instead of UINT_MAX to be consistent with the rest of Yarr code.
Sukolsak Sakshuwong
Comment 8
2018-07-01 09:47:37 PDT
Created
attachment 344051
[details]
Use Checked<unsigned, RecordOverflow> and quantifyInfinite
Sukolsak Sakshuwong
Comment 9
2018-07-01 10:02:42 PDT
Thanks. I personally think it is semantically inconsistent to check a value against UINT_MAX but return quantifyInfinite instead of UINT_MAX (I know they have the same value) if the value exceeds UINT_MAX. But since the rest of Yarr code seems to use quantifyInfinite heavily, I will use quantifyInfinite as you suggested.
Sukolsak Sakshuwong
Comment 10
2018-07-01 10:11:06 PDT
Created
attachment 344052
[details]
Forgot to update ChangeLog
Mark Lam
Comment 11
2018-07-01 13:41:35 PDT
Comment on
attachment 344052
[details]
Forgot to update ChangeLog View in context:
https://bugs.webkit.org/attachment.cgi?id=344052&action=review
I'd like Michael Saboff to take a look at the RegExp test changes.
> Source/JavaScriptCore/yarr/YarrParser.h:985 > + if (n.hasOverflowed()) { > + do { > + consume(); > + } while (peekIsDigit()); > + return quantifyInfinite; > + }
This extra overflow check is not needed because in the overflow case: 1. we still need to interate all digits anyway, and the cost of the computation of n is not that expensive, and 2. overflows rarely happen. We should favor the normal (non-overflow) case by not adding extra overflow checks to it.
> Source/JavaScriptCore/yarr/YarrParser.h:988 > + return n.unsafeGet();
Do this here: return n.hasOverflowed() ? quantifyInfinite : n.unsafeGet();
Darin Adler
Comment 12
2018-07-01 13:49:58 PDT
Comment on
attachment 344052
[details]
Forgot to update ChangeLog View in context:
https://bugs.webkit.org/attachment.cgi?id=344052&action=review
>> Source/JavaScriptCore/yarr/YarrParser.h:985 >> + } > > This extra overflow check is not needed because in the overflow case: 1. we still need to interate all digits anyway, and the cost of the computation of n is not that expensive, and 2. overflows rarely happen. We should favor the normal (non-overflow) case by not adding extra overflow checks to it.
So this loop should just be this: while (peekIsDigit()) n = n * 10 + consumeDigit(); Then the whole function will just be four lines long, just like the original version. And more straightforward than the original, too.
Mark Lam
Comment 13
2018-07-01 14:17:52 PDT
Comment on
attachment 344052
[details]
Forgot to update ChangeLog View in context:
https://bugs.webkit.org/attachment.cgi?id=344052&action=review
>>> Source/JavaScriptCore/yarr/YarrParser.h:985 >>> + } >> >> This extra overflow check is not needed because in the overflow case: 1. we still need to interate all digits anyway, and the cost of the computation of n is not that expensive, and 2. overflows rarely happen. We should favor the normal (non-overflow) case by not adding extra overflow checks to it. > > So this loop should just be this: > > while (peekIsDigit()) > n = n * 10 + consumeDigit(); > > Then the whole function will just be four lines long, just like the original version. And more straightforward than the original, too.
Oh, that's even better. I didn't think to use consumeDigit() but that is totally the way to go.
Sukolsak Sakshuwong
Comment 14
2018-07-01 14:41:29 PDT
Created
attachment 344061
[details]
Remove the extra overflow loop, use consumeDigit, and update ChangeLog
Saam Barati
Comment 15
2018-07-01 23:18:30 PDT
Comment on
attachment 344061
[details]
Remove the extra overflow loop, use consumeDigit, and update ChangeLog View in context:
https://bugs.webkit.org/attachment.cgi?id=344061&action=review
r=me
> Source/JavaScriptCore/ChangeLog:11 > + because once there has been overflow, undefined behavior has occurred.
This isn’t true. Unsigned overflow is defined behavior. Signed overflow is not. Your point below holds regardless
Sukolsak Sakshuwong
Comment 16
2018-07-02 17:07:39 PDT
Created
attachment 344153
[details]
Patch for landing
Sukolsak Sakshuwong
Comment 17
2018-07-02 17:09:16 PDT
(In reply to Saam Barati from
comment #15
)
> Comment on
attachment 344061
[details]
> Remove the extra overflow loop, use consumeDigit, and update ChangeLog > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=344061&action=review
> > r=me > > > Source/JavaScriptCore/ChangeLog:11 > > + because once there has been overflow, undefined behavior has occurred. > > This isn’t true. Unsigned overflow is defined behavior. Signed overflow is > not. Your point below holds regardless
Thanks. I didn't know this. I have removed that sentence from the ChangeLog.
WebKit Commit Bot
Comment 18
2018-07-02 17:49:54 PDT
Comment on
attachment 344153
[details]
Patch for landing Clearing flags on attachment: 344153 Committed
r233451
: <
https://trac.webkit.org/changeset/233451
>
WebKit Commit Bot
Comment 19
2018-07-02 17:49:56 PDT
All reviewed patches have been landed. Closing bug.
Radar WebKit Bug Importer
Comment 20
2018-07-02 17:50:45 PDT
<
rdar://problem/41750143
>
isol2
Comment 21
2018-08-08 09:02:31 PDT
cinfuzz
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug