|
| 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 | + |
0 commit comments