Buffer_is_accessed_out_of_bounds.patch 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. From 1e14e360cbb1418a4d4799d4b3a94dfb3b87f271 Mon Sep 17 00:00:00 2001
  2. From: chrchr-github <78114321+chrchr-github@users.noreply.github.com>
  3. Date: Mon, 29 Aug 2022 12:24:58 +0200
  4. Subject: [PATCH] Fix #8295 FN (error) Buffer is accessed out of bounds
  5. (wcpncpy, wcsncpy) (#4412)
  6. * Fix #8295 FN (error) Buffer is accessed out of bounds (wcpncpy, wcsncpy)
  7. * Fix cfg, validation
  8. * Fix validation
  9. ---
  10. cfg/cppcheck-cfg.rng | 19 ++++++++++++++++++-
  11. cfg/posix.cfg | 2 +-
  12. cfg/std.cfg | 2 +-
  13. lib/checkbufferoverrun.cpp | 12 +++++++++---
  14. lib/library.cpp | 6 +++---
  15. test/cfg/posix.c | 8 ++++++++
  16. test/cfg/std.c | 8 ++++++++
  17. 7 files changed, 48 insertions(+), 9 deletions(-)
  18. diff --git a/cfg/cppcheck-cfg.rng b/cfg/cppcheck-cfg.rng
  19. index b81a3533526..1f7b37de26b 100644
  20. --- a/cfg/cppcheck-cfg.rng
  21. +++ b/cfg/cppcheck-cfg.rng
  22. @@ -283,7 +283,6 @@
  23. <attribute name="type">
  24. <choice>
  25. <value>strlen</value>
  26. - <value>argvalue</value>
  27. <value>sizeof</value>
  28. <value>mul</value>
  29. </choice>
  30. @@ -310,6 +309,24 @@
  31. <attribute name="baseType"><text/></attribute>
  32. </optional>
  33. </element>
  34. + <element name="minsize">
  35. + <attribute name="type">
  36. + <choice>
  37. + <value>argvalue</value>
  38. + </choice>
  39. + </attribute>
  40. + <attribute name="arg">
  41. + <ref name="ARGNO"/>
  42. + </attribute>
  43. + <optional>
  44. + <attribute name="arg2">
  45. + <ref name="ARGNO"/>
  46. + </attribute>
  47. + </optional>
  48. + <optional>
  49. + <attribute name="baseType"><text/></attribute>
  50. + </optional>
  51. + </element>
  52. </choice>
  53. </zeroOrMore>
  54. <optional>
  55. diff --git a/cfg/posix.cfg b/cfg/posix.cfg
  56. index 9fa1597f433..83766ed1215 100644
  57. --- a/cfg/posix.cfg
  58. +++ b/cfg/posix.cfg
  59. @@ -5449,7 +5449,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
  60. <not-overlapping-data ptr1-arg="1" ptr2-arg="2" size-arg="3"/>
  61. <arg nr="1" direction="out">
  62. <not-null/>
  63. - <minsize type="argvalue" arg="3"/>
  64. + <minsize type="argvalue" arg="3" baseType="wchar_t"/>
  65. </arg>
  66. <arg nr="2" direction="in">
  67. <not-null/>
  68. diff --git a/cfg/std.cfg b/cfg/std.cfg
  69. index 86ce3954a2c..a7387dfb353 100644
  70. --- a/cfg/std.cfg
  71. +++ b/cfg/std.cfg
  72. @@ -5359,7 +5359,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
  73. <not-overlapping-data ptr1-arg="1" ptr2-arg="2" size-arg="3"/>
  74. <arg nr="1">
  75. <not-null/>
  76. - <minsize type="argvalue" arg="3"/>
  77. + <minsize type="argvalue" arg="3" baseType="wchar_t"/>
  78. </arg>
  79. <arg nr="2" direction="in">
  80. <not-null/>
  81. diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp
  82. index f929bdbeb73..d8160e81bab 100644
  83. --- a/lib/checkbufferoverrun.cpp
  84. +++ b/lib/checkbufferoverrun.cpp
  85. @@ -593,10 +593,16 @@ static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::Mi
  86. return Token::getStrLength(strtoken) < bufferSize;
  87. }
  88. break;
  89. - case Library::ArgumentChecks::MinSize::Type::ARGVALUE:
  90. - if (arg && arg->hasKnownIntValue())
  91. - return arg->getKnownIntValue() <= bufferSize;
  92. + case Library::ArgumentChecks::MinSize::Type::ARGVALUE: {
  93. + if (arg && arg->hasKnownIntValue()) {
  94. + MathLib::bigint myMinsize = arg->getKnownIntValue();
  95. + unsigned int baseSize = tokenizer->sizeOfType(minsize.baseType);
  96. + if (baseSize != 0)
  97. + myMinsize *= baseSize;
  98. + return myMinsize <= bufferSize;
  99. + }
  100. break;
  101. + }
  102. case Library::ArgumentChecks::MinSize::Type::SIZEOF:
  103. // TODO
  104. break;
  105. diff --git a/lib/library.cpp b/lib/library.cpp
  106. index c22d76c3cba..f74b000edb2 100644
  107. --- a/lib/library.cpp
  108. +++ b/lib/library.cpp
  109. @@ -783,9 +783,6 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
  110. return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, valueattr);
  111. ac.minsizes.emplace_back(type, 0);
  112. ac.minsizes.back().value = minsizevalue;
  113. - const char* baseTypeAttr = argnode->Attribute("baseType");
  114. - if (baseTypeAttr)
  115. - ac.minsizes.back().baseType = baseTypeAttr;
  116. } else {
  117. const char *argattr = argnode->Attribute("arg");
  118. if (!argattr)
  119. @@ -804,6 +801,9 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
  120. ac.minsizes.back().arg2 = arg2attr[0] - '0';
  121. }
  122. }
  123. + const char* baseTypeAttr = argnode->Attribute("baseType"); // used by VALUE, ARGVALUE
  124. + if (baseTypeAttr)
  125. + ac.minsizes.back().baseType = baseTypeAttr;
  126. }
  127. else if (argnodename == "iterator") {
  128. diff --git a/test/cfg/posix.c b/test/cfg/posix.c
  129. index aad6217ee20..195f86f8575 100644
  130. --- a/test/cfg/posix.c
  131. +++ b/test/cfg/posix.c
  132. @@ -564,6 +564,14 @@ size_t bufferAccessOutOfBounds_strnlen(const char *s, size_t maxlen)
  133. return len;
  134. }
  135. +void bufferAccessOutOfBounds_wcpncpy()
  136. +{
  137. + wchar_t s[16];
  138. + wcpncpy(s, L"abc", 16);
  139. + // cppcheck-suppress bufferAccessOutOfBounds
  140. + wcpncpy(s, L"abc", 17);
  141. +}
  142. +
  143. size_t nullPointer_strnlen(const char *s, size_t maxlen)
  144. {
  145. // No warning shall be shown:
  146. diff --git a/test/cfg/std.c b/test/cfg/std.c
  147. index 9ca3a61f06c..e60e9063704 100644
  148. --- a/test/cfg/std.c
  149. +++ b/test/cfg/std.c
  150. @@ -556,6 +556,14 @@ void bufferAccessOutOfBounds_wcsftime(wchar_t* ptr, size_t maxsize, const wchar_
  151. (void)wcsftime(ptr, maxsize, format, timeptr);
  152. }
  153. +void bufferAccessOutOfBounds_wcsncpy()
  154. +{
  155. + wchar_t s[16];
  156. + wcsncpy(s, L"abc", 16);
  157. + // cppcheck-suppress bufferAccessOutOfBounds
  158. + wcsncpy(s, L"abc", 17);
  159. +}
  160. +
  161. int nullPointer_wcsncmp(const wchar_t* s1, const wchar_t* s2, size_t n)
  162. {
  163. // cppcheck-suppress nullPointer