brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.9 KiB · 23e6329 Raw
379 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3;4; Verify that calls with arguments with pointers just past the end of5; a string to [a subset of] library functions that expect nul-terminated6; strings as arguments are folded to safe values.  The rationale is that7; since they are undefined and even though folding them isn't important8; for efficiency and prevents sanitizers from detecting and reporting9; them, sanitizers usually don't run, and transforming such invalid10; calls to something valid is safer than letting the program run off11; the rails.  See the Safe Optimizations for Sanitizers RFC for12; an in-depth discussion of the trade-offs:13; https://discourse.llvm.org/t/rfc-safe-optimizations-for-sanitizers14 15declare ptr @strchr(ptr, i32)16declare ptr @strrchr(ptr, i32)17declare i32 @strcmp(ptr, ptr)18declare i32 @strncmp(ptr, ptr, i64)19declare ptr @strstr(ptr, ptr)20 21declare ptr @stpcpy(ptr, ptr)22declare ptr @strcpy(ptr, ptr)23declare ptr @stpncpy(ptr, ptr, i64)24declare ptr @strncpy(ptr, ptr, i64)25 26declare i64 @strlen(ptr)27declare i64 @strnlen(ptr, i64)28 29declare ptr @strpbrk(ptr, ptr)30 31declare i64 @strspn(ptr, ptr)32declare i64 @strcspn(ptr, ptr)33 34declare i32 @atoi(ptr)35declare i64 @atol(ptr)36declare i64 @atoll(ptr)37declare i64 @strtol(ptr, ptr, i32)38declare i64 @strtoll(ptr, ptr, i32)39declare i64 @strtoul(ptr, ptr, i32)40declare i64 @strtoull(ptr, ptr, i32)41 42declare i32 @sprintf(ptr, ptr, ...)43declare i32 @snprintf(ptr, i64, ptr, ...)44 45 46@a5 = constant [5 x i8] c"%s\0045";47 48 49; Fold strchr(a5 + 5, '\0') to null.50 51define ptr @fold_strchr_past_end() {52; CHECK-LABEL: @fold_strchr_past_end(53; CHECK-NEXT:    ret ptr getelementptr inbounds nuw (i8, ptr @a5, i64 5)54;55  %p = getelementptr [5 x i8], ptr @a5, i32 0, i32 556  %q = call ptr @strchr(ptr %p, i32 0)57  ret ptr %q58}59 60; Fold strcmp(a5, a5 + 5) (and vice versa) to null.61 62define void @fold_strcmp_past_end(ptr %pcmp) {63; CHECK-LABEL: @fold_strcmp_past_end(64; CHECK-NEXT:    store i32 1, ptr [[PCMP:%.*]], align 465; CHECK-NEXT:    [[PC50:%.*]] = getelementptr i8, ptr [[PCMP]], i64 466; CHECK-NEXT:    store i32 -1, ptr [[PC50]], align 467; CHECK-NEXT:    ret void68;69  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 570 71  %c05 = call i32 @strcmp(ptr @a5, ptr %p5)72  store i32 %c05, ptr %pcmp73 74  %c50 = call i32 @strcmp(ptr %p5, ptr @a5)75  %pc50 = getelementptr i32, ptr %pcmp, i32 176  store i32 %c50, ptr %pc5077 78  ret void79}80 81 82; Likewise, fold strncmp(a5, a5 + 5, 5) (and vice versa) to null.83 84define void @fold_strncmp_past_end(ptr %pcmp) {85; CHECK-LABEL: @fold_strncmp_past_end(86; CHECK-NEXT:    store i32 1, ptr [[PCMP:%.*]], align 487; CHECK-NEXT:    [[PC50:%.*]] = getelementptr i8, ptr [[PCMP]], i64 488; CHECK-NEXT:    store i32 -1, ptr [[PC50]], align 489; CHECK-NEXT:    ret void90;91  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 592 93  %c05 = call i32 @strncmp(ptr @a5, ptr %p5, i64 5)94  store i32 %c05, ptr %pcmp95 96  %c50 = call i32 @strncmp(ptr %p5, ptr @a5, i64 5)97  %pc50 = getelementptr i32, ptr %pcmp, i32 198  store i32 %c50, ptr %pc5099 100  ret void101}102 103 104; Fold strrchr(a5 + 5, '\0') to poison (it's UB).105 106define ptr @fold_strrchr_past_end(i32 %c) {107; CHECK-LABEL: @fold_strrchr_past_end(108; CHECK-NEXT:    ret ptr poison109;110  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5111  %r = call ptr @strrchr(ptr %p5, i32 0)112  ret ptr %r113}114 115 116; Fold strstr(a5 + 5, a5) (and vice versa) to null.117 118define void @fold_strstr_past_end(ptr %psub) {119; CHECK-LABEL: @fold_strstr_past_end(120; CHECK-NEXT:    store ptr @a5, ptr [[PSUB:%.*]], align 8121; CHECK-NEXT:    [[PS50:%.*]] = getelementptr i8, ptr [[PSUB]], i64 8122; CHECK-NEXT:    store ptr null, ptr [[PS50]], align 8123; CHECK-NEXT:    ret void124;125  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5126 127  %s05 = call ptr @strstr(ptr @a5, ptr %p5)128  store ptr %s05, ptr %psub129 130  %s50 = call ptr @strstr(ptr %p5, ptr @a5)131  %ps50 = getelementptr ptr, ptr %psub, i32 1132  store ptr %s50, ptr %ps50133 134  ret void135}136 137 138; Fold strlen(a5 + 5) to 0.139 140define i64 @fold_strlen_past_end() {141; CHECK-LABEL: @fold_strlen_past_end(142; CHECK-NEXT:    ret i64 0143;144  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5145  %r = call i64 @strlen(ptr %p5)146  ret i64 %r147}148 149 150; TODO: Fold stpcpy(dst, a5 + 5) to (*dst = '\0', dst).151 152define ptr @fold_stpcpy_past_end(ptr %dst) {153; CHECK-LABEL: @fold_stpcpy_past_end(154; CHECK-NEXT:    ret ptr [[DST:%.*]]155;156  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5157  %r = call ptr @strcpy(ptr %dst, ptr %p5)158  ret ptr %r159}160 161 162; TODO: Fold strcpy(dst, a5 + 5) to (*dst = '\0', dst).163 164define ptr @fold_strcpy_past_end(ptr %dst) {165; CHECK-LABEL: @fold_strcpy_past_end(166; CHECK-NEXT:    ret ptr [[DST:%.*]]167;168  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5169  %r = call ptr @strcpy(ptr %dst, ptr %p5)170  ret ptr %r171}172 173 174; TODO: Fold stpncpy(dst, a5 + 5, 5) to (memset(dst, 0, 5), dst + 5).175 176define ptr @fold_stpncpy_past_end(ptr %dst) {177; CHECK-LABEL: @fold_stpncpy_past_end(178; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST:%.*]], i8 0, i64 5, i1 false)179; CHECK-NEXT:    ret ptr [[DST]]180;181  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5182  %r = call ptr @strncpy(ptr %dst, ptr %p5, i64 5)183  ret ptr %r184}185 186 187; TODO: Fold strncpy(dst, a5 + 5, 5) to memset(dst, 0, 5).188 189define ptr @fold_strncpy_past_end(ptr %dst) {190; CHECK-LABEL: @fold_strncpy_past_end(191; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(5) [[DST:%.*]], i8 0, i64 5, i1 false)192; CHECK-NEXT:    ret ptr [[DST]]193;194  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5195  %r = call ptr @strncpy(ptr %dst, ptr %p5, i64 5)196  ret ptr %r197}198 199 200; Fold strpbrk(a5, a5 + 5) (and vice versa) to null.201 202define void @fold_strpbrk_past_end(ptr %psub) {203; CHECK-LABEL: @fold_strpbrk_past_end(204; CHECK-NEXT:    store ptr null, ptr [[PSUB:%.*]], align 8205; CHECK-NEXT:    [[PS50:%.*]] = getelementptr i8, ptr [[PSUB]], i64 8206; CHECK-NEXT:    store ptr null, ptr [[PS50]], align 8207; CHECK-NEXT:    ret void208;209  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5210 211  %s05 = call ptr @strpbrk(ptr @a5, ptr %p5)212  store ptr %s05, ptr %psub213 214  %s50 = call ptr @strpbrk(ptr %p5, ptr @a5)215  %ps50 = getelementptr ptr, ptr %psub, i32 1216  store ptr %s50, ptr %ps50217 218  ret void219}220 221 222; Fold strspn(a5, a5 + 5) (and vice versa) to null.223 224define void @fold_strspn_past_end(ptr %poff) {225; CHECK-LABEL: @fold_strspn_past_end(226; CHECK-NEXT:    store i64 0, ptr [[POFF:%.*]], align 4227; CHECK-NEXT:    [[PO50:%.*]] = getelementptr i8, ptr [[POFF]], i64 8228; CHECK-NEXT:    store i64 0, ptr [[PO50]], align 4229; CHECK-NEXT:    ret void230;231  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5232 233  %o05 = call i64 @strspn(ptr @a5, ptr %p5)234  store i64 %o05, ptr %poff235 236  %o50 = call i64 @strspn(ptr %p5, ptr @a5)237  %po50 = getelementptr i64, ptr %poff, i32 1238  store i64 %o50, ptr %po50239 240  ret void241}242 243 244; Fold strcspn(a5, a5 + 5) (and vice versa) to null.245 246define void @fold_strcspn_past_end(ptr %poff) {247; CHECK-LABEL: @fold_strcspn_past_end(248; CHECK-NEXT:    store i64 2, ptr [[POFF:%.*]], align 4249; CHECK-NEXT:    [[PO50:%.*]] = getelementptr i8, ptr [[POFF]], i64 8250; CHECK-NEXT:    store i64 0, ptr [[PO50]], align 4251; CHECK-NEXT:    ret void252;253  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5254 255  %o05 = call i64 @strcspn(ptr @a5, ptr %p5)256  store i64 %o05, ptr %poff257 258  %o50 = call i64 @strcspn(ptr %p5, ptr @a5)259  %po50 = getelementptr i64, ptr %poff, i32 1260  store i64 %o50, ptr %po50261 262  ret void263}264 265 266; TODO: Fold the 32-bit atoi(a5 + 5) to zero.267; Verify that processing the invalid call doesn't run into trouble.268 269define i32 @fold_atoi_past_end() {270; CHECK-LABEL: @fold_atoi_past_end(271; CHECK-NEXT:    [[I:%.*]] = call i32 @atoi(ptr nonnull getelementptr inbounds nuw (i8, ptr @a5, i64 5))272; CHECK-NEXT:    ret i32 [[I]]273;274  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5275  %i = call i32 @atoi(ptr %p5)276  ret i32 %i277}278 279; TODO: Likewise, fold the 64-bit atol(a5 + 5) to zero, and similarly280; for atoll and strtrol and similar.281; Verify that processing the invalid call doesn't run into trouble.282 283define void @fold_atol_strtol_past_end(ptr %ps) {284; CHECK-LABEL: @fold_atol_strtol_past_end(285; CHECK-NEXT:    [[I0:%.*]] = call i64 @atol(ptr nonnull getelementptr inbounds nuw (i8, ptr @a5, i64 5))286; CHECK-NEXT:    store i64 [[I0]], ptr [[PS:%.*]], align 4287; CHECK-NEXT:    [[I1:%.*]] = call i64 @atoll(ptr nonnull getelementptr inbounds nuw (i8, ptr @a5, i64 5))288; CHECK-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[PS]], i64 8289; CHECK-NEXT:    store i64 [[I1]], ptr [[P1]], align 4290; CHECK-NEXT:    [[I2:%.*]] = call i64 @strtol(ptr nonnull captures(none) getelementptr inbounds nuw (i8, ptr @a5, i64 5), ptr null, i32 0)291; CHECK-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[PS]], i64 16292; CHECK-NEXT:    store i64 [[I2]], ptr [[P2]], align 4293; CHECK-NEXT:    [[I3:%.*]] = call i64 @strtoul(ptr nonnull captures(none) getelementptr inbounds nuw (i8, ptr @a5, i64 5), ptr null, i32 8)294; CHECK-NEXT:    [[P3:%.*]] = getelementptr i8, ptr [[PS]], i64 24295; CHECK-NEXT:    store i64 [[I3]], ptr [[P3]], align 4296; CHECK-NEXT:    [[I4:%.*]] = call i64 @strtoll(ptr nonnull captures(none) getelementptr inbounds nuw (i8, ptr @a5, i64 5), ptr null, i32 10)297; CHECK-NEXT:    [[P4:%.*]] = getelementptr i8, ptr [[PS]], i64 32298; CHECK-NEXT:    store i64 [[I4]], ptr [[P4]], align 4299; CHECK-NEXT:    [[I5:%.*]] = call i64 @strtoul(ptr nonnull captures(none) getelementptr inbounds nuw (i8, ptr @a5, i64 5), ptr null, i32 16)300; CHECK-NEXT:    [[P5:%.*]] = getelementptr i8, ptr [[PS]], i64 40301; CHECK-NEXT:    store i64 [[I5]], ptr [[P5]], align 4302; CHECK-NEXT:    ret void303;304  %pa5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5305 306  %i0 = call i64 @atol(ptr %pa5)307  store i64 %i0, ptr %ps308 309  %i1 = call i64 @atoll(ptr %pa5)310  %p1 = getelementptr i64, ptr %ps, i32 1311  store i64 %i1, ptr %p1312 313  %i2 = call i64 @strtol(ptr %pa5, ptr null, i32 0)314  %p2 = getelementptr i64, ptr %ps, i32 2315  store i64 %i2, ptr %p2316 317  %i3 = call i64 @strtoul(ptr %pa5, ptr null, i32 8)318  %p3 = getelementptr i64, ptr %ps, i32 3319  store i64 %i3, ptr %p3320 321  %i4 = call i64 @strtoll(ptr %pa5, ptr null, i32 10)322  %p4 = getelementptr i64, ptr %ps, i32 4323  store i64 %i4, ptr %p4324 325  %i5 = call i64 @strtoul(ptr %pa5, ptr null, i32 16)326  %p5 = getelementptr i64, ptr %ps, i32 5327  store i64 %i5, ptr %p5328 329  ret void330}331 332 333; Fold sprintf(dst, a5 + 5) to zero, and also334; TODO: fold sprintf(dst, "%s", a5 + 5) to zero.335 336define void @fold_sprintf_past_end(ptr %pcnt, ptr %dst) {337; CHECK-LABEL: @fold_sprintf_past_end(338; CHECK-NEXT:    store i32 0, ptr [[PCNT:%.*]], align 4339; CHECK-NEXT:    [[PN05:%.*]] = getelementptr i8, ptr [[PCNT]], i64 4340; CHECK-NEXT:    store i32 0, ptr [[PN05]], align 4341; CHECK-NEXT:    ret void342;343  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5344 345  %n5_ = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr %p5)346  store i32 %n5_, ptr %pcnt347 348  %n05 = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @a5, ptr %p5)349  %pn05 = getelementptr i32, ptr %pcnt, i32 1350  store i32 %n05, ptr %pn05351 352  ret void353}354 355 356; Fold snprintf(dst, n, a5 + 5) to zero, and also357; TODO: fold snprintf(dst, n, "%s", a5 + 5) to zero.358 359define void @fold_snprintf_past_end(ptr %pcnt, ptr %dst, i64 %n) {360; CHECK-LABEL: @fold_snprintf_past_end(361; CHECK-NEXT:    [[N5_:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST:%.*]], i64 [[N:%.*]], ptr nonnull getelementptr inbounds nuw (i8, ptr @a5, i64 5))362; CHECK-NEXT:    store i32 [[N5_]], ptr [[PCNT:%.*]], align 4363; CHECK-NEXT:    [[N05:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST]], i64 [[N]], ptr nonnull @a5, ptr nonnull getelementptr inbounds nuw (i8, ptr @a5, i64 5))364; CHECK-NEXT:    [[PN05:%.*]] = getelementptr i8, ptr [[PCNT]], i64 4365; CHECK-NEXT:    store i32 [[N05]], ptr [[PN05]], align 4366; CHECK-NEXT:    ret void367;368  %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5369 370  %n5_ = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %dst, i64 %n, ptr %p5)371  store i32 %n5_, ptr %pcnt372 373  %n05 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %dst, i64 %n, ptr @a5, ptr %p5)374  %pn05 = getelementptr i32, ptr %pcnt, i32 1375  store i32 %n05, ptr %pn05376 377  ret void378}379