Skip to content

Commit 04b5c9d

Browse files
committed
properly overflow gep arguments; fixes #1975
1 parent f034e39 commit 04b5c9d

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

src/parseTools.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1640,14 +1640,18 @@ function getFastValue(a, op, b, type) {
16401640
}
16411641

16421642
function getFastValues(list, op, type) {
1643-
assert(op == '+');
1643+
assert(op === '+' && type === 'i32');
1644+
for (var i = 0; i < list.length; i++) {
1645+
if (isNumber(list[i])) list[i] = (list[i]|0) + '';
1646+
}
16441647
var changed = true;
16451648
while (changed) {
16461649
changed = false;
16471650
for (var i = 0; i < list.length-1; i++) {
16481651
var fast = getFastValue(list[i], op, list[i+1], type);
16491652
var raw = list[i] + op + list[i+1];
16501653
if (fast.length < raw.length || fast.indexOf(op) < 0) {
1654+
if (isNumber(fast)) fast = (fast|0) + '';
16511655
list[i] = fast;
16521656
list.splice(i+1, 1);
16531657
i--;

tests/cases/gepaddoverflow.ll

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
; ModuleID = 'new.o'
2+
target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
3+
target triple = "le32-unknown-nacl"
4+
5+
declare i32 @printf(i8* noalias, ...) nounwind
6+
7+
@x = common global [4194304 x i8] zeroinitializer, align 4
8+
@.str = private constant [6 x i8] c"*%d*\0A\00", align 1
9+
10+
define i8* @test_gep(i32 %y) nounwind readnone {
11+
; JavaScript uses double precision 64-bit floating point values, with
12+
; a 53 bit mantissa. The maximum precisely representable integer is
13+
; 9007199254740992. A number close to that limit is constructed here
14+
; for the constant part of the getelementptr instruction:
15+
; 4194304 * 2147483647 == 9007199250546688 == 9007199254740992 - 4194304
16+
; If that number appears in JavaScript source instead of being properly
17+
; limited to 32 bits, the %y parameter can be used to exceed the maximum
18+
; precisely representable integer, and make the computation inexact.
19+
%test_res = getelementptr [4194304 x i8]* @x, i32 2147483647, i32 %y
20+
ret i8* %test_res
21+
}
22+
23+
define i32 @main() {
24+
%res_0 = call i8* (i32)* @test_gep(i32 1000000000)
25+
%res_1 = call i8* (i32)* @test_gep(i32 1000000001)
26+
%res_0_i = ptrtoint i8* %res_0 to i32
27+
%res_1_i = ptrtoint i8* %res_1 to i32
28+
29+
; If getelementptr limited the constant part of the offset to 32 bits,
30+
; result will be 1. Otherwise, it cannot be 1 because the large numbers in
31+
; the calculation cannot be accurately represented by floating point math.
32+
%res_diff = sub i32 %res_1_i, %res_0_i
33+
%printf_res = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i32 %res_diff)
34+
35+
ret i32 0
36+
}
37+

tests/cases/gepaddoverflow.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*1*

0 commit comments

Comments
 (0)