Index: clang/lib/Analysis/UnsafeBufferUsage.cpp =================================================================== --- clang/lib/Analysis/UnsafeBufferUsage.cpp +++ clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -132,6 +132,16 @@ return hasType(hasCanonicalType(pointerType())); } +// TODO use hasCanonicalType +static auto hasArrayType() { + return anyOf( + hasType(arrayType()), + hasType(autoType( + hasDeducedType(hasUnqualifiedDesugaredType(arrayType())))), + // ElaboratedType, e.g., typedef + hasType(elaboratedType(hasUnqualifiedDesugaredType(arrayType())))); +} + namespace { /// Gadget is an individual operation in the code that may be of interest to /// this analysis. Each (non-abstract) subclass corresponds to a specific @@ -292,9 +302,14 @@ static Matcher matcher() { // FIXME: What if the index is integer literal 0? Should this be // a safe gadget in this case? - return stmt(arraySubscriptExpr(hasBase(ignoringParenImpCasts(hasPointerType())), - unless(hasIndex(integerLiteral(equals(0))))) - .bind(ArraySubscrTag)); + +// clang-format off + return stmt(arraySubscriptExpr( + hasBase(ignoringParenImpCasts( + anyOf(hasPointerType(), hasArrayType()))), + unless(hasIndex(integerLiteral(equals(0))))) + .bind(ArraySubscrTag)); +// clang-format on } const ArraySubscriptExpr *getBaseStmt() const override { return ASE; } @@ -516,7 +531,7 @@ #include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def" // In parallel, match all DeclRefExprs so that to find out // whether there are any uncovered by gadgets. - declRefExpr(hasPointerType(), to(varDecl())).bind("any_dre"), + declRefExpr(anyOf(hasPointerType(), hasArrayType()), to(varDecl())).bind("any_dre"), // Also match DeclStmts because we'll need them when fixing // their underlying VarDecls that otherwise don't have // any backreferences to DeclStmts. Index: clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp @@ -49,11 +49,10 @@ int a[10], b[10][10]; - // Not to warn subscripts on arrays - foo(a[1], 1[a], - b[3][4], - 4[b][3], - 4[3[b]]); + foo(a[1], 1[a], // expected-warning2{{unchecked operation on raw buffer in expression}} + b[3][4], // expected-warning2{{unchecked operation on raw buffer in expression}} + 4[b][3], // expected-warning2{{unchecked operation on raw buffer in expression}} + 4[3[b]]); // expected-warning2{{unchecked operation on raw buffer in expression}} // Not to warn when index is zero foo(p[0], pp[0][0], 0[0[pp]], 0[pp][0], @@ -66,7 +65,6 @@ void testArraySubscriptsWithAuto(int *p, int **pp) { int a[10]; - auto ap1 = a; foo(ap1[1]); // expected-warning{{unchecked operation on raw buffer in expression}} @@ -96,8 +94,7 @@ foo(p[1], 1[p], p[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} q[1], 1[q], q[-1], // expected-warning3{{unchecked operation on raw buffer in expression}} a[1], // expected-warning{{unchecked operation on raw buffer in expression}} `a` is of pointer type - b[1][2], // expected-warning{{unchecked operation on raw buffer in expression}} `b[1]` is of array type - c[1] // `c` is of array type + b[1][2] // expected-warning2{{unchecked operation on raw buffer in expression}} `b[1]` is of array type ); } @@ -116,25 +113,25 @@ T_t * funRetTStar(); void testStructMembers(struct T * sp, struct T s, T_t * sp2, T_t s2) { - foo(sp->a[1], + foo(sp->a[1], // expected-warning{{unchecked operation on raw buffer in expression}} sp->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - sp->c.a[1], + sp->c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} sp->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - s.a[1], + s.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} s.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - s.c.a[1], + s.c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} s.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - sp2->a[1], + sp2->a[1], // expected-warning{{unchecked operation on raw buffer in expression}} sp2->b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - sp2->c.a[1], + sp2->c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} sp2->c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - s2.a[1], + s2.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} s2.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - s2.c.a[1], + s2.c.a[1], // expected-warning{{unchecked operation on raw buffer in expression}} s2.c.b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - funRetT().a[1], + funRetT().a[1], // expected-warning{{unchecked operation on raw buffer in expression}} funRetT().b[1], // expected-warning{{unchecked operation on raw buffer in expression}} - funRetTStar()->a[1], + funRetTStar()->a[1], // expected-warning{{unchecked operation on raw buffer in expression}} funRetTStar()->b[1] // expected-warning{{unchecked operation on raw buffer in expression}} ); } @@ -148,7 +145,7 @@ auto Lam = [p, a]() { return p[1] // expected-warning{{unchecked operation on raw buffer in expression}} - + a[1] + garray[1] + + a[1] + garray[1] // expected-warning2{{unchecked operation on raw buffer in expression}} + gp[1]; // expected-warning{{unchecked operation on raw buffer in expression}} }; } @@ -157,7 +154,7 @@ void testTypedefs(T_ptr_t p) { foo(p[1], // expected-warning{{unchecked operation on raw buffer in expression}} - p[1].a[1], // expected-warning{{unchecked operation on raw buffer in expression}} + p[1].a[1], // expected-warning2{{unchecked operation on raw buffer in expression}} p[1].b[1] // expected-warning2{{unchecked operation on raw buffer in expression}} ); } @@ -269,10 +266,45 @@ ); } -void testVariableDecls(int * p) { +int testVariableDecls(int * p) { int * q = p++; // expected-warning{{unchecked operation on raw buffer in expression}} int a[p[1]]; // expected-warning{{unchecked operation on raw buffer in expression}} int b = p[1]; // expected-warning{{unchecked operation on raw buffer in expression}} + return p[1]; // expected-warning{{unchecked operation on raw buffer in expression}} +} + +template void fArr(T t[]) { + foo(t[1]); // expected-warning{{unchecked operation on raw buffer in expression}} + T ar[8]; + foo(ar[5]); // expected-warning{{unchecked operation on raw buffer in expression}} +} + +template void fArr(int t[]); // expected-note {{in instantiation of function template specialization 'fArr' requested here}} + +int testReturn(int t[]) { + return t[1]; // expected-warning{{unchecked operation on raw buffer in expression}} } +//FIXME: Array access warnings on 0-indices;ArraySubscriptGadget excludes 0 index for both raw pointers and arrays! +int testArrayAccesses(int n) { + + // auto deduced array type + int cArr[2][3] = {{1, 2, 3}, {4, 5, 6}}; + int d = cArr[0][0]; + foo(cArr[0][0]); + foo(cArr[1][2]); // expected-warning2{{unchecked operation on raw buffer in expression}} + auto cPtr = cArr[1][2]; // expected-warning2{{unchecked operation on raw buffer in expression}} + foo(cPtr); + + // Typdefs + typedef int A[3]; + const A tArr = {4, 5, 6}; + foo(tArr[0], tArr[1]); // expected-warning{{unchecked operation on raw buffer in expression}} + return cArr[0][1]; // expected-warning{{unchecked operation on raw buffer in expression}} +} + + + + + #endif