Skip to content

Commit

Permalink
Merge pull request #16 from vahancho/left-shift-ub-fix
Browse files Browse the repository at this point in the history
Fix the undefined behaviour caused by left shifting of negative values.

fixes #15
  • Loading branch information
vahancho authored Oct 5, 2023
2 parents 9bed987 + 0666f2b commit 0182315
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 6 deletions.
25 changes: 19 additions & 6 deletions src/polylineencoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ class PolylineEncoder
Polyline m_polyline;

//! Constants
static const int s_chunkSize = 5;
static const int s_asciiOffset = 63;
static const int s_5bitMask = 0x1f; // 0b11111 = 31
static const int s_6bitMask = 0x20; // 0b100000 = 32
static constexpr const int s_chunkSize = 5;
static constexpr const int s_asciiOffset = 63;
static constexpr const int s_5bitMask = 0x1f; // 0b11111 = 31
static constexpr const int s_6bitMask = 0x20; // 0b100000 = 32
};

// A bogus class for compile-time precision calculations.
Expand Down Expand Up @@ -176,11 +176,24 @@ template<int Digits>
std::string PolylineEncoder<Digits>::encode(double value)
{
int32_t e5 =
std::round(value * Precision::Value); // (2)
std::round(value * Precision::Value); // (2)

const bool negativeValue = value < 0;

if (negativeValue) {
// Negative value must be calculated using
// its two's complement by inverting the
// binary value and adding one to the
// result // (3)

e5 *= -1; // Starting with the equivalent positive number;
e5 = ~e5; // Inverting (or flipping) all bits – changing every 0 to 1, and every 1 to 0;
e5 += 1; // Adding 1 to the entire inverted number.
}

e5 <<= 1; // (4)

if (value < 0) {
if (negativeValue) {
e5 = ~e5; // (5)
}

Expand Down
7 changes: 7 additions & 0 deletions test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ TEST(General, ZeroPoint)
EXPECT_EQ(encoder.encode(), "??");
}

TEST(General, NegativeValues)
{
gepaf::PolylineEncoder<> encoder;
encoder.addPoint(-77.9832104, -179.9832104);
EXPECT_EQ(encoder.encode(), "`b~zM`~oia@");
}

TEST(General, PolesAndEquator)
{
gepaf::PolylineEncoder<> encoder;
Expand Down

0 comments on commit 0182315

Please sign in to comment.