Skip to content

Commit

Permalink
Merge pull request #213 from boostorg/develop
Browse files Browse the repository at this point in the history
Changes for 1.86
  • Loading branch information
jefftrull authored Jun 27, 2024
2 parents c11757d + 46bd710 commit 13a8e17
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 29 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ TODO (known issues):

CHANGELOG

Boost V1.86:
- Fixed #197: Improper signed overflow handling (UB and a missing division check)
- Replaced usage of vsprintf() with the more secure vsnprintf()

Boost V1.85:
- Fixed #200: Emitted pragmas lack terminating newline
- Fixed #202: YYMARKER not updated when fill called on BOOST_WAVE_BSIZE boundary
Expand Down
7 changes: 4 additions & 3 deletions include/boost/wave/cpplexer/re2clex/cpp_re2c_lexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,12 +315,13 @@ lexer<IteratorT, PositionT, TokenT>::report_error(Scanner<IteratorT> const *s, i
BOOST_ASSERT(0 != s);
BOOST_ASSERT(0 != msg);

using namespace std; // some system have vsprintf in namespace std
using namespace std; // some systems have vsnprintf in namespace std

char buffer[200]; // should be large enough
constexpr std::size_t bufsize = 200; // should be large enough
char buffer[bufsize];
va_list params;
va_start(params, msg);
vsprintf(buffer, msg, params);
vsnprintf(buffer, bufsize, msg, params);
va_end(params);

BOOST_WAVE_LEXER_THROW_VAR(lexing_exception, errcode, buffer, s->line,
Expand Down
58 changes: 35 additions & 23 deletions include/boost/wave/grammars/cpp_expression_value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <iostream>
#endif // defined(BOOST_SPIRIT_DEBUG)

#include <limits>

#include <boost/wave/wave_config.hpp>
#include <boost/wave/grammars/cpp_value_error.hpp> // value_error

Expand Down Expand Up @@ -185,28 +187,30 @@ class closure_value {
switch(rhs.type) {
case is_bool:
{
int_literal_type result = value.i + as_long(rhs);
if ((rhs.value.i > 0L && value.i > result) ||
(rhs.value.i < 0L && value.i < result))
// bool is either 0 or 1
if (((std::numeric_limits<int_literal_type>::max)() - as_long(rhs)) < value.i)
{
// signed overflow will occur if addition performed
valid = error_integer_overflow;
}
else {
value.i = result;
value.i += as_long(rhs);
}
}
break;

case is_int:
{
int_literal_type result = value.i + rhs.value.i;
if ((rhs.value.i > 0L && value.i > result) ||
(rhs.value.i < 0L && value.i < result))
if (((rhs.value.i > 0) &&
(((std::numeric_limits<int_literal_type>::max)() - rhs.value.i) < value.i)) ||
((rhs.value.i < 0) &&
(((std::numeric_limits<int_literal_type>::min)() - rhs.value.i) > value.i)))
{
// signed overflow will occur if addition performed
valid = error_integer_overflow;
}
else {
value.i = result;
value.i += rhs.value.i;
}
}
break;
Expand Down Expand Up @@ -252,28 +256,29 @@ class closure_value {
switch(rhs.type) {
case is_bool:
{
int_literal_type result = value.i - as_long(rhs);
if ((rhs.value.i > 0L && result > value.i) ||
(rhs.value.i < 0L && result < value.i))
if (((std::numeric_limits<int_literal_type>::min)() + as_long(rhs)) > value.i)
{
// signed overflow will occur if subtraction performed
valid = error_integer_overflow;
}
else {
value.i = result;
value.i -= as_long(rhs);
}
}
break;

case is_int:
{
int_literal_type result = value.i - rhs.value.i;
if ((rhs.value.i > 0L && result > value.i) ||
(rhs.value.i < 0L && result < value.i))
if (((rhs.value.i < 0) &&
(((std::numeric_limits<int_literal_type>::max)() + rhs.value.i) < value.i)) ||
((rhs.value.i > 0) &&
(((std::numeric_limits<int_literal_type>::min)() + rhs.value.i) > value.i)))
{
// signed overflow will occur if subtraction performed
valid = error_integer_overflow;
}
else {
value.i = result;
value.i -= rhs.value.i;
}
}
break;
Expand Down Expand Up @@ -351,16 +356,22 @@ class closure_value {
case is_bool: value.i *= as_long(rhs); break;
case is_int:
{
int_literal_type result = value.i * rhs.value.i;
if (0 != value.i && 0 != rhs.value.i &&
(result / value.i != rhs.value.i ||
result / rhs.value.i != value.i)
)
// overflow tests for signed multiplication taken from
// Warren, Hacker's Delight, 2nd Ed. p32
int_literal_type mx = (std::numeric_limits<int_literal_type>::max)();
int_literal_type mn = (std::numeric_limits<int_literal_type>::min)();

bool ovflw =
(value.i > 0) ? ((rhs.value.i > 0) ? (value.i > (mx / rhs.value.i))
: (rhs.value.i < (mn / value.i)))
: ((rhs.value.i > 0) ? (value.i < (mn / rhs.value.i))
: ((value.i != 0) && (rhs.value.i < (mx / value.i))));
if (ovflw)
{
valid = error_integer_overflow;
}
else {
value.i = result;
value.i *= rhs.value.i;
}
}
break;
Expand Down Expand Up @@ -430,7 +441,8 @@ class closure_value {
case is_bool:
case is_int:
if (as_long(rhs) != 0) {
if (value.i == -value.i && -1 == rhs.value.i) {
if (std::numeric_limits<int_literal_type>::min() == value.i &&
-1 == rhs.value.i) {
// LONG_MIN / -1 on two's complement
valid = error_integer_overflow;
}
Expand Down
7 changes: 4 additions & 3 deletions samples/waveidl/idllexer/idl_re2c_lexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,13 @@ lexer<IteratorT, PositionT>::report_error(scanner_t const *s, int errcode,
BOOST_ASSERT(0 != s);
BOOST_ASSERT(0 != msg);

using namespace std; // some system have vsprintf in namespace std
using namespace std; // some systems have vsnprintf in namespace std

char buffer[200]; // should be large enough
constexpr std::size_t bufsize = 200; // should be large enough
char buffer[bufsize];
va_list params;
va_start(params, msg);
vsprintf(buffer, msg, params);
vsnprintf(buffer, bufsize, msg, params);
va_end(params);

BOOST_WAVE_LEXER_THROW_VAR(boost::wave::cpplexer::lexing_exception,
Expand Down
21 changes: 21 additions & 0 deletions test/testwave/testfiles/t_6_070.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
http://www.boost.org/
Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
Software License, Version 1.0. (See accompanying file
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
The tests included in this file were initially taken from the mcpp V2.5
preprocessor validation suite and were modified to fit into the Boost.Wave
unit test requirements.
The original files of the mcpp preprocessor are distributed under the
license reproduced at the end of this file.
=============================================================================*/

// Tests error reporting: overflow of constant expression in #if directive.

// 14.10:
//E t_6_070.cpp(20): error: integer overflow in preprocessor expression: $E(__TESTWAVE_LONG_MIN__) / - 1
#if __TESTWAVE_LONG_MIN__ / - 1
#endif
1 change: 1 addition & 0 deletions test/testwave/testfiles/test.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ t_6_066.cpp
t_6_067.cpp
t_6_068.cpp
t_6_069.cpp
t_6_070.cpp

#
# t_7: C++0x testing
Expand Down

0 comments on commit 13a8e17

Please sign in to comment.