summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2014-03-20 03:32:39 +0000
committerJordan Rose <jordan_rose@apple.com>2014-03-20 03:32:39 +0000
commit177b0a3600d8d3eaf6ccbf573d0bf053c4b24191 (patch)
treedcb3ee4883bf4c0e8d855f7664a9314107039b94 /clang
parentda0de8a237de508c99f06e93928301e0d2c0f24b (diff)
downloadbcm5719-llvm-177b0a3600d8d3eaf6ccbf573d0bf053c4b24191.tar.gz
bcm5719-llvm-177b0a3600d8d3eaf6ccbf573d0bf053c4b24191.zip
scanf format checking: include the buffer length in the fix-it for %s.
Patch by Zach Davis! llvm-svn: 204300
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Analysis/Analyses/FormatString.h3
-rw-r--r--clang/lib/Analysis/ScanfFormatString.cpp23
-rw-r--r--clang/lib/Sema/SemaChecking.cpp5
-rw-r--r--clang/test/Sema/format-strings-fixit.c28
4 files changed, 48 insertions, 11 deletions
diff --git a/clang/include/clang/Analysis/Analyses/FormatString.h b/clang/include/clang/Analysis/Analyses/FormatString.h
index c9516b50cae..3bffcd3ce00 100644
--- a/clang/include/clang/Analysis/Analyses/FormatString.h
+++ b/clang/include/clang/Analysis/Analyses/FormatString.h
@@ -572,7 +572,8 @@ public:
ArgType getArgType(ASTContext &Ctx) const;
- bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx);
+ bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,
+ ASTContext &Ctx);
void toString(raw_ostream &os) const;
diff --git a/clang/lib/Analysis/ScanfFormatString.cpp b/clang/lib/Analysis/ScanfFormatString.cpp
index f5ce84fe361..3ff7f0ad2e5 100644
--- a/clang/lib/Analysis/ScanfFormatString.cpp
+++ b/clang/lib/Analysis/ScanfFormatString.cpp
@@ -379,21 +379,23 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
return ArgType();
}
-bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
+bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
+ const LangOptions &LangOpt,
ASTContext &Ctx) {
- if (!QT->isPointerType())
- return false;
// %n is different from other conversion specifiers; don't try to fix it.
if (CS.getKind() == ConversionSpecifier::nArg)
return false;
+ if (!QT->isPointerType())
+ return false;
+
QualType PT = QT->getPointeeType();
// If it's an enum, get its underlying type.
- if (const EnumType *ETy = QT->getAs<EnumType>())
- QT = ETy->getDecl()->getIntegerType();
-
+ if (const EnumType *ETy = PT->getAs<EnumType>())
+ PT = ETy->getDecl()->getIntegerType();
+
const BuiltinType *BT = PT->getAs<BuiltinType>();
if (!BT)
return false;
@@ -405,6 +407,15 @@ bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
LM.setKind(LengthModifier::AsWideChar);
else
LM.setKind(LengthModifier::None);
+
+ // If we know the target array length, we can use it as a field width.
+ if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
+ if (CAT->getSizeModifier() == ArrayType::Normal)
+ FieldWidth = OptionalAmount(OptionalAmount::Constant,
+ CAT->getSize().getZExtValue() - 1,
+ "", 0, false);
+
+ }
return true;
}
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 74ca197b8de..e45f2e53337 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3518,8 +3518,9 @@ bool CheckScanfHandler::HandleScanfSpecifier(
const analyze_format_string::ArgType &AT = FS.getArgType(S.Context);
if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType())) {
ScanfSpecifier fixedFS = FS;
- bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
- S.Context);
+ bool success = fixedFS.fixType(Ex->getType(),
+ Ex->IgnoreImpCasts()->getType(),
+ S.getLangOpts(), S.Context);
if (success) {
// Get the fix string from the fixed format specifier.
diff --git a/clang/test/Sema/format-strings-fixit.c b/clang/test/Sema/format-strings-fixit.c
index 31274185cbc..d9d7fb3fbad 100644
--- a/clang/test/Sema/format-strings-fixit.c
+++ b/clang/test/Sema/format-strings-fixit.c
@@ -14,6 +14,7 @@ typedef __SIZE_TYPE__ size_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
+typedef __WCHAR_TYPE__ wchar_t;
void test() {
// Basic types
@@ -97,11 +98,14 @@ void test() {
int scanf(char const *, ...);
-void test2() {
+void test2(int intSAParm[static 2]) {
char str[100];
+ char *vstr = "abc";
+ wchar_t wstr[100];
short shortVar;
unsigned short uShortVar;
int intVar;
+ int intAVar[2];
unsigned uIntVar;
float floatVar;
double doubleVar;
@@ -114,11 +118,22 @@ void test2() {
intmax_t intmaxVar;
uintmax_t uIntmaxVar;
ptrdiff_t ptrdiffVar;
+ enum {A, B, C} enumVar;
+ // Some string types.
scanf("%lf", str);
+ scanf("%lf", vstr);
+ scanf("%ls", str);
+ scanf("%f", wstr); // FIXME: wchar_t should resolve to %ls, not %d.
+ scanf("%s", wstr); // FIXME: wchar_t should resolve to %ls, not %d.
+ scanf("%ls", str);
+
+ // Some integer types.
scanf("%f", &shortVar);
scanf("%f", &uShortVar);
scanf("%p", &intVar);
+ scanf("%f", intAVar);
+ scanf("%f", intSAParm);
scanf("%Lf", &uIntVar);
scanf("%ld", &floatVar);
scanf("%f", &doubleVar);
@@ -127,6 +142,7 @@ void test2() {
scanf("%f", &uLongVar);
scanf("%f", &longLongVar);
scanf("%f", &uLongLongVar);
+ scanf("%d", &enumVar); // FIXME: We ought to fix specifiers for enums.
// Some named ints.
scanf("%f", &sizeVar);
@@ -206,10 +222,17 @@ void test2() {
// CHECK: printf("%La", (long double) 42);
// CHECK: printf("%LA", (long double) 42);
-// CHECK: scanf("%s", str);
+// CHECK: scanf("%99s", str);
+// CHECK: scanf("%s", vstr);
+// CHECK: scanf("%99s", str);
+// CHECK: scanf("%d", wstr);
+// CHECK: scanf("%d", wstr);
+// CHECK: scanf("%99s", str);
// CHECK: scanf("%hd", &shortVar);
// CHECK: scanf("%hu", &uShortVar);
// CHECK: scanf("%d", &intVar);
+// CHECK: scanf("%d", intAVar);
+// CHECK: scanf("%d", intSAParm);
// CHECK: scanf("%u", &uIntVar);
// CHECK: scanf("%f", &floatVar);
// CHECK: scanf("%lf", &doubleVar);
@@ -218,6 +241,7 @@ void test2() {
// CHECK: scanf("%lu", &uLongVar);
// CHECK: scanf("%lld", &longLongVar);
// CHECK: scanf("%llu", &uLongLongVar);
+// CHECK: scanf("%d", &enumVar);
// CHECK: scanf("%zu", &sizeVar);
// CHECK: scanf("%jd", &intmaxVar);
// CHECK: scanf("%ju", &uIntmaxVar);
OpenPOWER on IntegriCloud