Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix undefined behaviour #646

Merged
merged 16 commits into from
Jun 15, 2016
Merged

Fix undefined behaviour #646

merged 16 commits into from
Jun 15, 2016

Conversation

efidler
Copy link
Contributor

@efidler efidler commented May 31, 2016

Fix issues with undefined behaviour, mostly found by running the unittests under UBSAN on Clang/OSX and GCC5/Linux.

Issue #644

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling e41b04a on efidler:ubsan into e6895ec on miloyip:master.

@coveralls
Copy link

coveralls commented May 31, 2016

Coverage Status

Coverage remained the same at 100.0% when pulling d27a255 on efidler:ubsan into e6895ec on miloyip:master.

@efidler efidler mentioned this pull request May 31, 2016
@@ -952,12 +956,16 @@ class GenericValue {
if (IsUint64()) {
uint64_t u = GetUint64();
volatile double d = static_cast<double>(u);
return static_cast<uint64_t>(d) == u;
return (d >= 0.0)
&& (d < (static_cast<double>(std::numeric_limits<uint64_t>::max()/2 + 1)) * 2)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Casting a double that's out-of-range for the uint64_t is undefined behaviour, so this equality test has undefined results. I'm not 100% clear on what exactly IsLosslessDouble promises if it returns true, but it's certainly possible that you could get true from the equality test when you expect false.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about the calculation (max / 2 + 1) * 2. I think it can simply construct a maximum double that can be converted to uint64_t.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is UINT64_MAX can't be exactly represented in a double. I changed it to be strictly less than UINT64_MAX as a double and added some more tests.

@coveralls
Copy link

coveralls commented Jun 1, 2016

Coverage Status

Coverage remained the same at 100.0% when pulling 875a9e1 on efidler:ubsan into e6895ec on miloyip:master.

@coveralls
Copy link

coveralls commented Jun 2, 2016

Coverage Status

Coverage remained the same at 100.0% when pulling 6923197 on efidler:ubsan into e6895ec on miloyip:master.

@efidler
Copy link
Contributor Author

efidler commented Jun 6, 2016

any more concerns? is this ready to merge?

@miloyip
Copy link
Collaborator

miloyip commented Jun 7, 2016

Travis reported that clang build were failed. Can you try to solve that? Thanks.

@efidler
Copy link
Contributor Author

efidler commented Jun 7, 2016

it looks like travis is failing to create the clang toolchain in the VM. I don't think it has anything to do with the code itself.

@efidler
Copy link
Contributor Author

efidler commented Jun 7, 2016

Yes, LLVM removed their apt mirror, which broken travis builds for tons of projects. We could move to the Trusty Travis environment and use the built-in clang, which is 3.5.

@miloyip
Copy link
Collaborator

miloyip commented Jun 7, 2016

Thank you. I just realized this. I will try to fix the build before merging for safety.
travis-ci/travis-ci#6120

@miloyip
Copy link
Collaborator

miloyip commented Jun 10, 2016

Hi, I tried on OSX and seems the compiler version of clang is different. I tried to fixed with this:

--- a/test/unittest/CMakeLists.txt
+++ b/test/unittest/CMakeLists.txt
@@ -1,3 +1,5 @@
+include(CheckCXXCompilerFlag)
+
 set(UNITTEST_SOURCES
        allocatorstest.cpp
     bigintegertest.cpp
@@ -41,7 +43,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
     # If the user is running a newer version of Clang that includes the
     # -Wdouble-promotion, we will ignore that warning.
     if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.7)
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-double-promotion")
+        CHECK_CXX_COMPILER_FLAG("-Wno-double-promotion" HAS_NO_DOUBLE_PROMOTION)
+        if (HAS_NO_DOUBLE_PROMOTION)
+            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-double-promotion")
+        endif()
     endif()
 elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
     # Force to always compile with /W4

Besides, there are problems in MSVC compilation in appveyor. Can you check if they can be fixed?

efidler added 8 commits June 13, 2016 07:24
…chable-code

clang advises: "note: silence by adding parentheses to mark code as explicitly dead"
specifically, "expression with side effects has no effect in an unevaluated context"
UBSAN gave "runtime error: index 13 out of bounds for type 'const uint32_t [10]'"
UBSAN gave issues with the typeless Schema:
runtime error: reference binding to null pointer of type 'rapidjson::GenericSchemaDocument<rapidjson::GenericValue<rapidjson::UTF16<wchar_t>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >, rapidjson::CrtAllocator>'
and
runtime error: member access within null pointer of type 'AllocatorType' (aka 'rapidjson::CrtAllocator')
UBSAN on Clang/Linux gave:
runtime error: null pointer passed as argument 2, which is declared to never be null
/usr/include/string.h:43:45: note: nonnull attribute specified here
@coveralls
Copy link

coveralls commented Jun 13, 2016

Coverage Status

Coverage remained the same at 100.0% when pulling 9eeae8d on efidler:ubsan into 2e66339 on miloyip:master.

@coveralls
Copy link

coveralls commented Jun 13, 2016

Coverage Status

Coverage remained the same at 100.0% when pulling 9eeae8d on efidler:ubsan into 2e66339 on miloyip:master.

@miloyip
Copy link
Collaborator

miloyip commented Jun 14, 2016

I merged #654 and fixed some compiling issues with that.
Hope this PR can be updated as well. Thanks.

efidler added 8 commits June 14, 2016 07:01
UBSAN gave for test/unittest/itoatest.cpp:87:
runtime error: signed integer overflow: 4611686018427387904 * 2 cannot be represented in type 'long'
maybe these tests should just be deleted?

UBSAN gave:
runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'long'
runtime error: signed integer overflow: -9223372036854775808 - 2 cannot be represented in type 'long'
UBSAN gave:
runtime error: division by zero
UBSAN gave during Reader.ParseNumber_FullPrecisionDouble test:
include/rapidjson/internal/strtod.h:149:11: runtime error: shift exponent 46 is too large for 32-bit type 'int'
UBSAN gave in Regex.Unicode test:
include/rapidjson/encodings.h:157:28: runtime error: shift exponent 32 is too large for 32-bit type 'int'
note that std::numeric_limits<uint64_t>::max() and
std::numeric_limits<int64_t>::max() aren't exactly representable in a
double, so we need to be strictly less to be definitely lossless

UBSAN gave during Value.IsLosslessDouble test:
include/rapidjson/document.h:955:42: runtime error: value 1.84467e+19 is outside the range of representable values of type 'unsigned long'
UBSAN gave in Value.IsLosslessFloat:
include/rapidjson/document.h:981:38: runtime error: value 3.40282e+38 is outside the range of representable values of type 'float'
@efidler
Copy link
Contributor Author

efidler commented Jun 14, 2016

I just pushed an update. Sorry for the slow progress; I'm travelling.

@coveralls
Copy link

coveralls commented Jun 14, 2016

Coverage Status

Coverage remained the same at 100.0% when pulling 8c40597 on efidler:ubsan into 2e66339 on miloyip:master.

@efidler
Copy link
Contributor Author

efidler commented Jun 14, 2016

ok, build passed

@miloyip miloyip merged commit 62ff0a9 into Tencent:master Jun 15, 2016
@miloyip
Copy link
Collaborator

miloyip commented Jun 15, 2016

Thank you very much.

@miloyip miloyip mentioned this pull request Jun 16, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants