Closed
Bug 501124
Opened 16 years ago
Closed 16 years ago
Missing strtointeger path in js_StringToInt32
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
VERIFIED
FIXED
People
(Reporter: bugs, Assigned: gal)
References
Details
(Keywords: regression, testcase, verified1.9.1, Whiteboard: fixed-in-tracemonkey)
Attachments
(2 files, 5 obsolete files)
|
905 bytes,
patch
|
brendan
:
review+
|
Details | Diff | Splinter Review |
|
837 bytes,
patch
|
beltzner
:
approval1.9.1.2+
|
Details | Diff | Splinter Review |
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)
As with FF 3.5 RC3 our ECMAScript/JavaScript based cryptographic login functions do not work anymore.
It seems that some basic operators do not work correctly, at least when the calculation is performed without artificial delays.
The bug is possibly exploitable.
Reproducible: Always
Steps to Reproduce:
The script below shows at least a part of the problem.
Compare the results of the script with FF < 3.5, Internet Explorer, and other browsers.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript">
function doTheTest()
{
var hexVal = "00000000000000000000000000000000DEADBABE";
var nblk = (((hexVal.length/2) + 8) >> 6) + 1;
var blks = new Array(nblk * 16);
for(var i = 0; i < nblk * 16; i++)
blks[i] = 0;
for(i = 0; i < hexVal.length; i++) {
blks[i >> 3] |= ("0x"+hexVal.charAt(i)) << (28 - (i % 8) * 4);
slowDown(300); // uncomment this line to make the script work (300 suffices on my machine)
}
alert(blks);
}
function slowDown(millis)
{
var date = new Date();
var curDate = null;
do {
curDate = new Date();
} while(curDate - date < millis);
}
</script>
</head>
<body>
<form>
<input type="button" name="go" onclick="doTheTest();" value="go"/>
</form>
</body>
</html>
Actual Results:
FF 3.5 RC3 does not calculate the same results as older FF versions, and other browsers.
Expected Results:
FF 3.5 should calculate the same results as older FF versions, and other browsers.
Comment 1•16 years ago
|
||
Updated•16 years ago
|
Assignee: nobody → general
Component: General → JavaScript Engine
Product: Firefox → Core
QA Contact: general → general
Version: unspecified → Trunk
Comment 2•16 years ago
|
||
This testcase behaves differently on current mozilla-1.9.1, tracemonkey and m-c tips depending on whether the JIT is enabled:
[gavin@gavin-mbp:~/obj-js-tracemonkey]$ ./js -f ~/test_501124.js
0,0,0,0,-559039810,0,0,0,0,0,0,0,0,0,0,0
[gavin@gavin-mbp:~/obj-js-tracemonkey]$ ./js -j -f ~/test_501124.js
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
The non-JIT behavior is consistent with Firefox 3.
Attachment #385746 -
Attachment is obsolete: true
Updated•16 years ago
|
Status: UNCONFIRMED → NEW
Ever confirmed: true
The previous script was accidentally posted with uncommented slowDown-call.
Comment 4•16 years ago
|
||
Do sites use this? The testcase gives me a slow script warning, which makes me
wonder if it's a problem with the wider web or not.
Comment 5•16 years ago
|
||
bogomip, can you provide more information about what application this breaks?
Flags: blocking1.9.1?
Keywords: regression,
testcase
Updated•16 years ago
|
Attachment #385750 -
Attachment is obsolete: true
Comment 7•16 years ago
|
||
Copying some of our best regression window finders.
> Do sites use this? The testcase gives me a slow script warning, which makes me
> wonder if it's a problem with the wider web or not.
The script was accidentally posted with the uncommented slowDown-call.
If you remove the respective line, the script will work as in production
environments.
See also Comment #3.
(In reply to comment #6)
> Did this just break in rc3?
A colleague of mine said that it worked in a previous RC or beta. He will try
to find out which version it was.
| Reporter | ||
Comment 10•16 years ago
|
||
(In reply to comment #9)
> A colleague of mine said that it worked in a previous RC or beta. He will try
> to find out which version it was.
It worked in
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1a2) Gecko/20080829071937 Shiretoko/3.1a2
Comment 11•16 years ago
|
||
Well, Shiretoko/3.1a2 was the last release where JIT was off by default, so that basically puts the range at "where JIT was turned on."
| Assignee | ||
Updated•16 years ago
|
Assignee: general → gal
| Assignee | ||
Comment 12•16 years ago
|
||
Confirmed. This is bad. Digging into it. Doesn't look hard.
| Reporter | ||
Comment 13•16 years ago
|
||
(In reply to comment #5)
> bogomip, can you provide more information about what application this breaks?
The application is a portal software. It has about 4000 installations.
The script is based upon a popular SHA-1 script from
http://pajhome.org.uk/crypt/md5/index.html.
| Reporter | ||
Comment 14•16 years ago
|
||
(In reply to comment #12)
> Confirmed. This is bad. Digging into it. Doesn't look hard.
Note that it is probably a race condition ;)
| Assignee | ||
Comment 15•16 years ago
|
||
partially reduced testcase
var hexVal = "DEADBABE";
var blks = new Array(4);
for(var i = 0; i < 4; i++)
blks[i] = 0;
for(i = 0; i < hexVal.length; i++) {
print(("0x"+hexVal.charAt(i)) << (28 - (i % 8) * 4));
}
| Assignee | ||
Comment 16•16 years ago
|
||
var hexVal = "DEAD";
for(i = 0; i < hexVal.length; i++)
print(("0x"+hexVal.charAt(i)) << (28 - (i % 8) * 4));
| Assignee | ||
Comment 17•16 years ago
|
||
for(i = 0; i < 4; i++)
print(("0x"+'D') << (28 - (i % 8) * 4));
| Assignee | ||
Comment 18•16 years ago
|
||
This breaks:
for(i = 0; i < 4; i++)
print(("0x" + "D") << (28 - (i % 8) * 4));
This works:
for(i = 0; i < 4; i++)
print(("0xD") << (28 - (i % 8) * 4));
| Assignee | ||
Comment 19•16 years ago
|
||
This smells like a register allocation bug to me (we had one that had just the same symptoms), but I have to reduce further. The shift op (<<) requires ECX, and the concat op might be spilling it or something weird. Just a guess. I will reduce a bit more.
Comment 20•16 years ago
|
||
FWIW, this worked in 9a9070f84098 (with JIT enabled) and bisection points to ce02fcaa233d, but that's just when we started tracing charAt.
| Assignee | ||
Comment 21•16 years ago
|
||
I would say this qualifies for scary:
for(i = 0; i < 4; i++)
print(("0x" + "D") << 16);
851968
851968
851968
851968
851968
851968
851968
0
| Assignee | ||
Comment 22•16 years ago
|
||
without jit:
851968
851968
851968
851968
with jit:
851968
851968
851968
0
| Assignee | ||
Comment 23•16 years ago
|
||
This still breaks. I am betting on regalloc. Digging into the assembly now.
for(i = 0; i < 4; i++)
print(("0xD" + "") << 16);
| Assignee | ||
Comment 24•16 years ago
|
||
Much easier to look at at the assembly level:
var x = 0;
for(i = 0; i < 4; i++)
x = ("0xD" + "") << 16;
print(x);
| Assignee | ||
Comment 25•16 years ago
|
||
Ok, this is fortunately not regalloc, but a highly specific number conversion bug. When converting a hex number to an integer, we fail:
js_StringToInt32(JSContext* cx, JSString* str)
{
const jschar* bp;
const jschar* end;
const jschar* ep;
jsdouble d;
str->getCharsAndEnd(bp, end);
- if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end)
+ if ((!js_strtod(cx, bp, end, &ep, &d) ||
+ js_SkipWhiteSpace(ep, end) != end) &&
+ (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
+ js_SkipWhiteSpace(ep, end) != end)) {
return 0;
+ }
return js_DoubleToECMAInt32(d);
}
JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, 1)
We have a specialized function to convert strings to numbers that is used when we know that the result is used like an integer. The << op forces this to happen. In the integer special casing somehow we lost strtointeger, which does the hex conversion. Patch in a sec.
| Assignee | ||
Comment 26•16 years ago
|
||
Awesome original shell testcase by the way, sped up identifying the issue tremendously. Thanks.
Attachment #385749 -
Attachment is obsolete: true
| Assignee | ||
Comment 27•16 years ago
|
||
patch contains some accidental changes, please ignore
| Assignee | ||
Comment 28•16 years ago
|
||
Attachment #385774 -
Attachment is obsolete: true
| Assignee | ||
Comment 29•16 years ago
|
||
regressor: http://hg.mozilla.org/tracemonkey/rev/3e6f2131c8b6
this is ancient
Comment 30•16 years ago
|
||
A Whistler-era bug from me, wonderful. The workaround would be to use decimal, I guess? Definitely will take this fix for 3.5.1 (subject to test and review), need to decide if we want to stop-ship for this now, hrm.
Flags: blocking1.9.1.1+
| Assignee | ||
Comment 31•16 years ago
|
||
Note: I simply copied the code from a working function above:
jsdouble FASTCALL
js_StringToNumber(JSContext* cx, JSString* str)
{
const jschar* bp;
const jschar* end;
const jschar* ep;
jsdouble d;
str->getCharsAndEnd(bp, end);
if ((!js_strtod(cx, bp, end, &ep, &d) ||
js_SkipWhiteSpace(ep, end) != end) &&
(!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
js_SkipWhiteSpace(ep, end) != end)) {
return js_NaN;
}
return d;
}
JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, 1)
So this should be a very safe and minimal fix.
| Assignee | ||
Comment 32•16 years ago
|
||
Simple work around:
var x = 0;
for(i = 0; i < 4; i++)
x = ("0xD" + "") * 1 << 16;
print(x);
The multiplication does not force the result to be an integer, so we take the js_StringToNumber slow path instead of the buggy js_StringToInt32 path.
| Assignee | ||
Comment 33•16 years ago
|
||
Comment 34•16 years ago
|
||
Comment on attachment 385776 [details] [diff] [review]
clean patch
This excerpts from js_ValueToNumber (could have an inline helper for use here and there as a followup). Better than a "bigger" (in control flow novelty) change (second patch, which is deceptively short-looking but IMHO bigger in possible unwanted effects).
/be
Attachment #385776 -
Flags: review+
Updated•16 years ago
|
Attachment #385779 -
Attachment is obsolete: true
| Assignee | ||
Updated•16 years ago
|
Keywords: regressionwindow-wanted
OS: Windows XP → All
Priority: -- → P2
Hardware: x86 → All
Summary: Firefox 3.5 RC3 JavaScript breaks cryptographic login routines → Missing strtointeger path in js_StringToInt32
Target Milestone: --- → mozilla1.9.1
Comment 35•16 years ago
|
||
I don't think we need to stop the ship of Firefox 3.5 for this, as it hasn't expressed itself in the large since we started shipping it in nightlies back in October or through a near-year's worth of betas.
That said, and as Shaver's blocking flag indicates, let's take the fix in 3.5.1.
Flags: blocking1.9.1? → blocking1.9.1-
OS: All → Windows XP
Priority: P2 → --
Hardware: All → x86
Target Milestone: mozilla1.9.1 → ---
| Assignee | ||
Comment 36•16 years ago
|
||
Whiteboard: fixed-in-tracemonkey
| Assignee | ||
Comment 38•16 years ago
|
||
We should land this on trunk soon.
Comment 39•16 years ago
|
||
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
Comment 41•16 years ago
|
||
Andreas: Please request approval on a patch that applies to 1.9.1.
Updated•16 years ago
|
blocking1.9.1: --- → .2+
Flags: blocking1.9.1.1+ → blocking1.9.1.1-
Comment 42•16 years ago
|
||
This fix is trivially safe and the bug is biting other sites (see dups). There's no reason for this fix to miss 1.9.1.1.
Andreas is gonna get a patch attached (but it may well be the same as the patch attached here -- Sam, did that patch not apply or what?).
/be
| Assignee | ||
Comment 43•16 years ago
|
||
Trivial conflict resolved.
Attachment #388595 -
Flags: approval1.9.1.1?
Comment 44•16 years ago
|
||
(In reply to comment #42)
> Sam, did that patch not apply or what?
I don't test to see if patches apply. If the patch here applies, you can request approval on it. It's simply a way of making sure developers check to see if their patches apply before requesting approval.
This missed 1.9.1.1 because we're in firedrill mode. It'll block 1.9.1.2 though.
| Assignee | ||
Comment 45•16 years ago
|
||
The patch should apply cleanly. Could someone please land on 1.9.1?
The conflict was a simple renaming that 1.9.1 doesn't have yet.
This is not security sensitive but it bites crypto algorithms in JS in particular.
The fix has been on m-c for a while and is very safe.
Flags: blocking1.9.1.1- → blocking1.9.1.1?
| Assignee | ||
Comment 46•16 years ago
|
||
Removing blocking 1.9.1.1? as per #44.
| Assignee | ||
Comment 47•16 years ago
|
||
Well I guess I can't take that back?
Comment 48•16 years ago
|
||
You should be able to *remove* it, but not put it back to minus.
Flags: blocking1.9.1.1? → blocking1.9.1.1-
Comment 49•16 years ago
|
||
In general, if people want things on the branch, they should be asking for approval when they know they have a patch that works on the branch, and landing as early as they can -- waiting until we're at the cusp of code freeze to try to get it in is worse for everyone. If we'd had a 1.9.1 patch with an approval request any time in the 9 days after the m-c landing, this would have been in 3.5.1 for sure!
Comment 50•16 years ago
|
||
Comment on attachment 388595 [details] [diff] [review]
patch for 1.9.1
a=beltzner for 1.9.1.2, please land on mozilla-1.9.1 (and be careful with that merge!)
Attachment #388595 -
Flags: approval1.9.1.1? → approval1.9.1.2+
Comment 52•16 years ago
|
||
status1.9.1:
--- → .2-fixed
Comment 55•16 years ago
|
||
http://hg.mozilla.org/tracemonkey/rev/58d20947e6f2
/cvsroot/mozilla/js/tests/js1_5/Regress/regress-501124.js,v <-- regress-501124.js
initial revision: 1.1
Flags: in-testsuite+
You need to log in
before you can comment on or make changes to this bug.
Description
•