/// size_t dstsize);
TLI_DEFINE_ENUM_INTERNAL(strlcpy_chk)
TLI_DEFINE_STRING_INTERNAL("__strlcpy_chk")
+/// char *__strlen_chk(const char *s1, size_t s1size);
+TLI_DEFINE_ENUM_INTERNAL(strlen_chk)
+TLI_DEFINE_STRING_INTERNAL("__strlen_chk")
/// char *strncat_chk(char *s1, const char *s2, size_t n, size_t s1size);
TLI_DEFINE_ENUM_INTERNAL(strncat_chk)
TLI_DEFINE_STRING_INTERNAL("__strncat_chk")
/// Str/Stp cpy are similar enough to be handled in the same functions.
Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
+ Value *optimizeStrLenChk(CallInst *CI, IRBuilder<> &B);
Value *optimizeMemCCpyChk(CallInst *CI, IRBuilder<> &B);
Value *optimizeSNPrintfChk(CallInst *CI, IRBuilder<> &B);
Value *optimizeSPrintfChk(CallInst *CI,IRBuilder<> &B);
FTy.getParamType(1)->isPointerTy() &&
FTy.getParamType(2)->isPointerTy() &&
FTy.getReturnType()->isIntegerTy(32));
+ case LibFunc_strlen_chk:
+ --NumParams;
+ if (!IsSizeTTy(FTy.getParamType(NumParams)))
+ return false;
+ LLVM_FALLTHROUGH;
case LibFunc_strlen:
return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() &&
FTy.getReturnType()->isIntegerTy());
// Try to further simplify the result.
CallInst *SimplifiedCI = dyn_cast<CallInst>(SimplifiedFortifiedCI);
if (SimplifiedCI && SimplifiedCI->getCalledFunction()) {
+ // Ensure that SimplifiedCI's uses are complete, since some calls have
+ // their uses analyzed.
+ replaceAllUsesWith(CI, SimplifiedCI);
+
// Use an IR Builder from SimplifiedCI if available instead of CI
// to guarantee we reach all uses we might replace later on.
IRBuilder<> TmpBuilder(SimplifiedCI);
return Ret;
}
+Value *FortifiedLibCallSimplifier::optimizeStrLenChk(CallInst *CI,
+ IRBuilder<> &B) {
+ if (isFortifiedCallFoldable(CI, 1, None, 0))
+ return emitStrLen(CI->getArgOperand(0), B, CI->getModule()->getDataLayout(),
+ TLI);
+ return nullptr;
+}
+
Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,
IRBuilder<> &B,
LibFunc Func) {
case LibFunc_stpcpy_chk:
case LibFunc_strcpy_chk:
return optimizeStrpCpyChk(CI, Builder, Func);
+ case LibFunc_strlen_chk:
+ return optimizeStrLenChk(CI, Builder);
case LibFunc_stpncpy_chk:
case LibFunc_strncpy_chk:
return optimizeStrpNCpyChk(CI, Builder, Func);
--- /dev/null
+; Test that __strlen_chk simplification works correctly.
+;
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+
+@hello = constant [6 x i8] c"hello\00"
+@hello_no_nul = constant [5 x i8] c"hello"
+
+declare i32 @__strlen_chk(i8*, i32)
+
+; Check __strlen_chk(string constant) -> strlen or constants
+
+; CHECK-LABEL: @unknown_str_known_object_size
+define i32 @unknown_str_known_object_size(i8* %c) {
+ ; CHECK: call i32 @__strlen_chk
+ %1 = call i32 @__strlen_chk(i8* %c, i32 8)
+ ret i32 %1
+}
+
+; CHECK-LABEL: @known_str_known_object_size
+define i32 @known_str_known_object_size(i8* %c) {
+ ; CHECK: ret i32 5
+ %1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6)
+ ret i32 %1
+}
+
+; CHECK-LABEL: @known_str_too_small_object_size
+define i32 @known_str_too_small_object_size(i8* %c) {
+ ; CHECK: call i32 @__strlen_chk
+ %1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 5)
+ ret i32 %1
+}
+
+; CHECK-LABEL: @known_str_no_nul
+define i32 @known_str_no_nul(i8* %c) {
+ ; CHECK: call i32 @__strlen_chk
+ %1 = call i32 @__strlen_chk(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_no_nul, i32 0, i32 0), i32 5)
+ ret i32 %1
+}
+
+; CHECK-LABEL: @unknown_str_unknown_object_size
+define i32 @unknown_str_unknown_object_size(i8* %c) {
+ ; CHECK: call i32 @strlen
+ %1 = call i32 @__strlen_chk(i8* %c, i32 -1)
+ ret i32 %1
+}
"declare i32 @__sprintf_chk(i8*, i32, i64, i8*, ...)\n"
"declare i8* @__strcat_chk(i8*, i8*, i64)\n"
"declare i64 @__strlcat_chk(i8*, i8*, i64, i64)\n"
+ "declare i64 @__strlen_chk(i8*, i64)\n"
"declare i8* @__strncat_chk(i8*, i8*, i64, i64)\n"
"declare i64 @__strlcpy_chk(i8*, i8*, i64, i64)\n"
"declare i32 @__vsnprintf_chk(i8*, i64, i32, i64, i8*, %struct*)\n"