This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Add check of sprintf with fixed size buffer
Needs ReviewPublic

Authored by Yoorkin on Aug 20 2022, 6:26 AM.

Details

Summary

Hi, I have added a clang-tidy check which proposed in this issue.
The check can finds sprintf usage like:

char buff[50];
sprintf(buff,"Hello, %s!\n","world");

And suggest counted version function instead:

warning: string to be written may exceeds the size of buffer; use snprintf instead [bugprone-sprintf-with-fixed-size-buffer]
  sprintf(buff,"Hello, %s!\n","world");
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  snprintf(buff, sizeof(buff), "Hello, %s!\n", "world")

Diff Detail

Event Timeline

Yoorkin created this revision.Aug 20 2022, 6:26 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 20 2022, 6:26 AM
Yoorkin requested review of this revision.Aug 20 2022, 6:26 AM
Eugene.Zelenko added inline comments.
clang-tools-extra/clang-tidy/bugprone/SprintfWithFixedSizeBufferCheck.cpp
14

Unnecessary newline.

35

const auto * could be used because type is spelled in same statement.

36

Ditto.

clang-tools-extra/clang-tidy/bugprone/SprintfWithFixedSizeBufferCheck.h
30

Please add isLanguageVersionSupported (C and C++).

clang-tools-extra/docs/ReleaseNotes.rst
105

Please use first statement in documentation.

clang-tools-extra/docs/clang-tidy/checks/bugprone/sprintf-with-fixed-size-buffer.rst
7

Please omit The check and use double back-ticks for sprintf (language construct).

8

Ditto for snprintf.

15

Please separate with newline.

22

Ditto.

40

Please fix.

Eugene.Zelenko edited reviewers, added: alexfh, aaron.ballman, njames93, LegalizeAdulthood; removed: Restricted Project.Aug 20 2022, 6:35 AM
Eugene.Zelenko set the repository for this revision to rG LLVM Github Monorepo.
Yoorkin added inline comments.Aug 20 2022, 8:05 AM
clang-tools-extra/clang-tidy/bugprone/SprintfWithFixedSizeBufferCheck.h
30

can i just simply use

bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
  return LangOpts.C99 || LangOpts.CPlusPlus11;
}

I think the check should be supported after C99 and Cpp11 standards. But i don't know whether it return true when language version is c++20 or C11

Eugene.Zelenko added inline comments.Aug 20 2022, 8:16 AM
clang-tools-extra/clang-tidy/bugprone/SprintfWithFixedSizeBufferCheck.h
30

snprintf is part of standard C library, so it could be used in early C and C++ standards.

Yoorkin updated this revision to Diff 454226.Aug 20 2022, 9:10 AM
Yoorkin marked 10 inline comments as done.

I fixed them all

Eugene.Zelenko added inline comments.Aug 20 2022, 9:13 AM
clang-tools-extra/docs/clang-tidy/checks/bugprone/sprintf-with-fixed-size-buffer.rst
7

Should be Finds. Same in Release Notes.

Yoorkin updated this revision to Diff 454228.Aug 20 2022, 9:18 AM

I fixed it. Thanks

Why are we only targeting sprintf, vsprintf would also suffer from the same pitfalls.
Is there any hard reason that this check always suggests snprintf instead of sprintf_s, maybe have that dynamically controlled with an option.

clang-tools-extra/clang-tidy/bugprone/SprintfWithFixedSizeBufferCheck.cpp
37

Prefer small little edits instead of one big replacement.
So create a fix it that turns sprintf into snprintf, then create a fix it that inserts , sizeof(Buff) after the first argument.

Yoorkin updated this revision to Diff 454722.Aug 23 2022, 12:48 AM

Now it can find usage of both sprintf and vsprintf, and then change a small piece of code. Here is an option PreferSafe, when value is true, the check prefers snprintf_s vsnprintf_s over snprintf vsnprintf.

Yoorkin updated this revision to Diff 454724.Aug 23 2022, 12:55 AM

I forgot to update comments in PrintfWithFixedSizeBufferCheck.h, sorry

Should this check be renamed to bugprone-sprintf-with-fixed-size-buffer?
Have you thought about an option to flag all calls to sprintf as they are typically not recommended by a lot of coding practice guides. Obviously we couldn't generate a fix-it as the buffer size may be unknown, but it could help fix someone's buffer overflow exploit.

clang-tools-extra/clang-tidy/bugprone/PrintfWithFixedSizeBufferCheck.cpp
23 ↗(On Diff #454724)
29 ↗(On Diff #454724)

Check out the mapAnyWith matcher, would simply a lot of this code.

33 ↗(On Diff #454724)

Just use hasAnyName("::sprintf", "::vsprintf"), Then in the check you can call getName to find out which one.

58–70 ↗(On Diff #454724)

Avoid string manipulation where possible.

clang-tools-extra/clang-tidy/bugprone/PrintfWithFixedSizeBufferCheck.h
27 ↗(On Diff #454724)

Let template deduction handle this.

30 ↗(On Diff #454724)

This check seems like it would have value in C code as well as C++.

Yoorkin updated this revision to Diff 458155.Sep 6 2022, 6:33 AM
Yoorkin marked 5 inline comments as done.

Maybe renamed to bugprone-sprintf-with-fixed-size-buffer would be better. I add another option FlagAllCalls to flag all calls to sprintf and vsprintf.

I want to enable this check in both c and c++, but didn't find option LangOpt.C. For c++, we have option LangOpt.CPlusPlus. There is only some specific c standard option like C99 C11 C17 and C2X defined in LangOptions.def. Could you tell me how to do this?

LegalizeAdulthood resigned from this revision.Mar 29 2023, 8:23 AM