This is an archive of the discontinued LLVM Phabricator instance.

improve clang's static analysis of __builtin_sprintf_chk()
AbandonedPublic

Authored by samparker on May 11 2015, 8:12 AM.

Details

Summary

Issue: https://llvm.org/bugs/show_bug.cgi?id=21124

Patch to improve Clang's static analysis of
__builtin_sprintf_chk so that it will outperform the
analysis of g++.

Diff Detail

Event Timeline

samparker updated this revision to Diff 25474.May 11 2015, 8:12 AM
samparker retitled this revision from to improve clang's static analysis of __builtin_sprintf_chk().
samparker updated this object.
samparker edited the test plan for this revision. (Show Details)
samparker added a subscriber: Unknown Object (MLST).
danalbert added subscribers: danalbert, srhines.

Hi Guys,

Has anyone been able to look at this yet? Its been a while and I understand it was a blocker for building android with clang.

Cheers,
sam

rtrieu edited edge metadata.Jun 15 2015, 3:35 PM

Hi Sam,

I'm just seeing this now since Phab didn't email me when I was added as a reviewer. I will review the patch this week.

Richard

These are comments about everything besides the actual checking code. I will review that next.

  1. Double warnings are coming up because the format strings are being checked twice. Clang already knows that __builtin___sprintf_chk has a format string, so that gets checked with the old diagnostics. Instead of calling the checks directly, modify the existing path to carry extra information along.
    • Add an argument bool IsSprintf at the end of Sema::CheckFormatArguments
    • When Sema::CheckFormatArguments is called in Sema::checkCall, set that argument to true if FDecl is a FunctionDecl that is the function __builtin___sprintf_chk
    • In Sema::CheckFormatArguments, if IsSprintf is true, set the type to FST_Sprintf, otherwise, use the current type.
  1. From testing, your patch looks limited in a few areas. The limitations of this warning should be documented with your CheckSprintfHandler class. For instance, non-specifiers text in the format string isn't counted. There's two ways to go from here:
  1. See http://llvm.org/docs/Phabricator.html about how to add full context to your patches. Full context makes reviewing patches easier.
include/clang/Sema/Sema.h
8524–8527

Remove.

8569

Add comment that this is not a format string attribute, but extra checking on top of a printf format string.

lib/Sema/SemaChecking.cpp
483–485

Remove.

1323–1356

Remove.

3395

Don't make unrelated whitespace changes in your patch.

4091–4094

Do you care that the expression is exactly a DeclRefExpr? It doens't seem important to this warning and you can remove everything except the return statement.

4106

Remove isObjC parameter.

4113

Replace isObjC with /*isObjC=*/ false.

4124

What is this function indicating? It needs a better name, a comment, or both.

4136–4137

Why are APInt's used here instead of an integer type?

4250–4251

A new diagnostic message should be created with more information than the current overflow diagnostic, and added to the format warning group.

4512

Remove this line and remove this parameter from the constructor, since the type is known at this point.

4519

Replace with /*isFreeBSDKPrintf=*/false)

test/SemaCXX/sprintf-chk.cpp
1 ↗(On Diff #25474)

There is nothing C++ about this. Move test to test/Sema/ directory.

13 ↗(On Diff #25474)

Move the expected-warning to the next line and use the @-1 to declare the warning comes from the previous line.

line_generating_warning();
// expected-warning@-1 {{warning message}}

Also, make sure that at least one of the expected-warning checks the whole warning message. Right now, they all check truncated versions of the warning.

rtrieu added inline comments.Jun 19 2015, 4:26 PM
lib/Sema/SemaChecking.cpp
4168

This seems backwards. You using the type of expression to determine how to calculate the value. You should use the argument type along with a switch statement to handle all the different specifiers.

4172

Another problem of trying to match expressions is that there are plenty of strange cases, for instance, negative numbers are actually positive numbers wrapped in a unary negative expression. Also, constants won't show up, or 1+1. Instead, use the Evaluate* methods in Expr. If it is a compile time constant, then Evaulate* will provide the value.

4226–4228

This is kind of tricky. Pointers have an implementation defined printing style. We should make sure that this takes into account how different implementations print pointers.

4236

StorageRequired is the total size needed for the entire string, not just the space required for this specifier. A local size is needed so that the extra width is added on correctly.

samparker updated this revision to Diff 28789.Jun 30 2015, 8:58 AM
samparker edited edge metadata.

Thanks for all the feedback and tips, I have hopefully addressed the comments from the first patch by:

  • reorganised the patch so that it only uses the printf specifier expression checker,
  • I have also removed the CheckSprintfHandler class and moved the functionality into CheckPrintfHandler,
  • used a switch statement on ConversionSpecifier::Kind to check each specifier,
  • used Expr functionality to evaluate constant integer expressions,
  • added platform specific checks for pointer formatting,
  • I have created a specific error message which reports the size needed.

cheers,

Hi Richard,

Have you had a chance to look at the revision?

Thanks,
sam

samparker abandoned this revision.Jan 4 2017, 5:48 AM