Skip to content

Commit 0a04f41

Browse files
authored
fix #37880, overflow in shift amount range check in codegen (#37891)
1 parent 40c3b2e commit 0a04f41

File tree

2 files changed

+55
-19
lines changed

2 files changed

+55
-19
lines changed

src/intrinsics.cpp

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,25 +1183,45 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **arg
11831183
case or_int: return ctx.builder.CreateOr(x, y);
11841184
case xor_int: return ctx.builder.CreateXor(x, y);
11851185

1186-
case shl_int:
1187-
return ctx.builder.CreateSelect(
1188-
ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1189-
t->getPrimitiveSizeInBits())),
1190-
ConstantInt::get(t, 0),
1191-
ctx.builder.CreateShl(x, uint_cnvt(ctx, t, y)));
1192-
case lshr_int:
1193-
return ctx.builder.CreateSelect(
1194-
ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1195-
t->getPrimitiveSizeInBits())),
1196-
ConstantInt::get(t, 0),
1197-
ctx.builder.CreateLShr(x, uint_cnvt(ctx, t, y)));
1198-
case ashr_int:
1199-
return ctx.builder.CreateSelect(
1200-
ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1201-
t->getPrimitiveSizeInBits())),
1202-
ctx.builder.CreateAShr(x, ConstantInt::get(t, t->getPrimitiveSizeInBits() - 1)),
1203-
ctx.builder.CreateAShr(x, uint_cnvt(ctx, t, y)));
1204-
1186+
case shl_int: {
1187+
Value *the_shl = ctx.builder.CreateShl(x, uint_cnvt(ctx, t, y));
1188+
if (ConstantInt::isValueValidForType(y->getType(), t->getPrimitiveSizeInBits())) {
1189+
return ctx.builder.CreateSelect(
1190+
ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1191+
t->getPrimitiveSizeInBits())),
1192+
ConstantInt::get(t, 0),
1193+
the_shl);
1194+
}
1195+
else {
1196+
return the_shl;
1197+
}
1198+
}
1199+
case lshr_int: {
1200+
Value *the_shr = ctx.builder.CreateLShr(x, uint_cnvt(ctx, t, y));
1201+
if (ConstantInt::isValueValidForType(y->getType(), t->getPrimitiveSizeInBits())) {
1202+
return ctx.builder.CreateSelect(
1203+
ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1204+
t->getPrimitiveSizeInBits())),
1205+
ConstantInt::get(t, 0),
1206+
the_shr);
1207+
}
1208+
else {
1209+
return the_shr;
1210+
}
1211+
}
1212+
case ashr_int: {
1213+
Value *the_shr = ctx.builder.CreateAShr(x, uint_cnvt(ctx, t, y));
1214+
if (ConstantInt::isValueValidForType(y->getType(), t->getPrimitiveSizeInBits())) {
1215+
return ctx.builder.CreateSelect(
1216+
ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1217+
t->getPrimitiveSizeInBits())),
1218+
ctx.builder.CreateAShr(x, ConstantInt::get(t, t->getPrimitiveSizeInBits() - 1)),
1219+
the_shr);
1220+
}
1221+
else {
1222+
return the_shr;
1223+
}
1224+
}
12051225
case bswap_int: {
12061226
FunctionCallee bswapintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::bswap, makeArrayRef(t));
12071227
return ctx.builder.CreateCall(bswapintr, x);

test/compiler/codegen.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,19 @@ let d = Dict((:a,) => 1, (:a, :b) => 2)
479479
@test d[(:a,)] == 1
480480
@test d[(:a, :b)] == 2
481481
end
482+
483+
# issue #37880
484+
primitive type Has256Bits 256 end
485+
let x = reinterpret(Has256Bits, [0xfcdac822cac89d82de4f9b3326da8294, 0x6ebac4d5982880ca703c57e37657f1ee])[]
486+
shifted = [0xeefcdac822cac89d82de4f9b3326da82, 0x006ebac4d5982880ca703c57e37657f1]
487+
f(x) = Base.lshr_int(x, 0x8)
488+
@test reinterpret(UInt128, [f(x)]) == shifted
489+
@test reinterpret(UInt128, [Base.lshr_int(x, 0x8)]) == shifted
490+
g(x) = Base.ashr_int(x, 0x8)
491+
@test reinterpret(UInt128, [g(x)]) == shifted
492+
@test reinterpret(UInt128, [Base.ashr_int(x, 0x8)]) == shifted
493+
lshifted = [0xdac822cac89d82de4f9b3326da829400, 0xbac4d5982880ca703c57e37657f1eefc]
494+
h(x) = Base.shl_int(x, 0x8)
495+
@test reinterpret(UInt128, [h(x)]) == lshifted
496+
@test reinterpret(UInt128, [Base.shl_int(x, 0x8)]) == lshifted
497+
end

0 commit comments

Comments
 (0)