| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 42359ab commit cf59e87
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -843,14 +843,15 @@ void CBORTokenizer::ReadNextToken(bool enter_envelope) { | |||
| 843 | 843 | return; | |
| 844 | 844 | case MajorType::NEGATIVE: { // INT32. | |
| 845 | 845 | // INT32 is a signed int32 (int32 makes sense for the | |
| 846 | - // inspector_protocol, it's not a CBOR limitation); in CBOR, | ||
| 847 | - // the negative values for INT32 are represented as NEGATIVE, | ||
| 848 | - // that is, -1 INT32 is represented as 1 << 5 | 0 (major type 1, | ||
| 849 | - // additional info value 0). So here, we compute the INT32 value | ||
| 850 | - // and then check it against the INT32 min. | ||
| 851 | - int64_t actual_value = | ||
| 852 | - -static_cast<int64_t>(token_start_internal_value_) - 1; | ||
| 853 | - if (!success || actual_value < std::numeric_limits<int32_t>::min()) { | ||
| 846 | + // inspector_protocol, it's not a CBOR limitation); in CBOR, the | ||
| 847 | + // negative values for INT32 are represented as NEGATIVE, that is, -1 | ||
| 848 | + // INT32 is represented as 1 << 5 | 0 (major type 1, additional info | ||
| 849 | + // value 0). The minimal allowed INT32 value in our protocol is | ||
| 850 | + // std::numeric_limits<int32_t>::min(). We check for it by directly | ||
| 851 | + // checking the payload against the maximal allowed signed (!) int32 | ||
| 852 | + // value. | ||
| 853 | + if (!success || token_start_internal_value_ > | ||
| 854 | + std::numeric_limits<int32_t>::max()) { | ||
| 854 | 855 | SetError(Error::CBOR_INVALID_INT32); | |
| 855 | 856 | return; | |
| 856 | 857 | } | |
@@ -1857,7 +1858,7 @@ class JsonParser { | |||
| 1857 | 1858 | // If the |Char| we're dealing with is really a byte, then | |
| 1858 | 1859 | // we have utf8 here, and we need to check for multibyte characters | |
| 1859 | 1860 | // and transcode them to utf16 (either one or two utf16 chars). | |
| 1860 | - if (sizeof(Char) == sizeof(uint8_t) && c >= 0x7f) { | ||
| 1861 | + if (sizeof(Char) == sizeof(uint8_t) && c > 0x7f) { | ||
| 1861 | 1862 | // Inspect the leading byte to figure out how long the utf8 | |
| 1862 | 1863 | // byte sequence is; while doing this initialize |codepoint| | |
| 1863 | 1864 | // with the first few bits. | |
@@ -1896,7 +1897,7 @@ class JsonParser { | |||
| 1896 | 1897 | // Disallow overlong encodings for ascii characters, as these | |
| 1897 | 1898 | // would include " and other characters significant to JSON | |
| 1898 | 1899 | // string termination / control. | |
| 1899 | - if (codepoint < 0x7f) | ||
| 1900 | + if (codepoint <= 0x7f) | ||
| 1900 | 1901 | return false; | |
| 1901 | 1902 | // Invalid in UTF8, and can't be represented in UTF16 anyway. | |
| 1902 | 1903 | if (codepoint > 0x10ffff) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -234,6 +234,24 @@ TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) { | |||
| 234 | 234 | EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); | |
| 235 | 235 | } | |
| 236 | 236 | ||
| 237 | + TEST(EncodeDecodeInt32Test, RoundtripsInt32Min) { | ||
| 238 | + // std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte. | ||
| 239 | + std::vector<uint8_t> encoded; | ||
| 240 | + EncodeInt32(std::numeric_limits<int32_t>::min(), &encoded); | ||
| 241 | + // 1 for initial byte, 4 for the uint32. | ||
| 242 | + // first three bits: major type = 1; | ||
| 243 | + // remaining five bits: additional info = 26, indicating payload is uint32. | ||
| 244 | + EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 5>{ | ||
| 245 | + {1 << 5 | 26, 0x7f, 0xff, 0xff, 0xff}})); | ||
| 246 | + | ||
| 247 | + // Reverse direction: decode with CBORTokenizer. | ||
| 248 | + CBORTokenizer tokenizer(SpanFrom(encoded)); | ||
| 249 | + EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag()); | ||
| 250 | + EXPECT_EQ(std::numeric_limits<int32_t>::min(), tokenizer.GetInt32()); | ||
| 251 | + tokenizer.Next(); | ||
| 252 | + EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); | ||
| 253 | + } | ||
| 254 | + | ||
| 237 | 255 | TEST(EncodeDecodeInt32Test, CantRoundtripUint32) { | |
| 238 | 256 | // 0xdeadbeef is a value which does not fit below | |
| 239 | 257 | // std::numerical_limits<int32_t>::max(), so we can't encode | |
@@ -261,15 +279,21 @@ TEST(EncodeDecodeInt32Test, DecodeErrorCases) { | |||
| 261 | 279 | std::vector<uint8_t> data; | |
| 262 | 280 | std::string msg; | |
| 263 | 281 | }; | |
| 264 | - std::vector<TestCase> tests{ | ||
| 265 | - {TestCase{ | ||
| 266 | - {24}, | ||
| 267 | - "additional info = 24 would require 1 byte of payload (but it's 0)"}, | ||
| 268 | - TestCase{{27, 0xaa, 0xbb, 0xcc}, | ||
| 269 | - "additional info = 27 would require 8 bytes of payload (but " | ||
| 270 | - "it's 3)"}, | ||
| 271 | - TestCase{{29}, "additional info = 29 isn't recognized"}}}; | ||
| 272 | - | ||
| 282 | + std::vector<TestCase> tests{{ | ||
| 283 | + TestCase{ | ||
| 284 | + {24}, | ||
| 285 | + "additional info = 24 would require 1 byte of payload (but it's 0)"}, | ||
| 286 | + TestCase{{27, 0xaa, 0xbb, 0xcc}, | ||
| 287 | + "additional info = 27 would require 8 bytes of payload (but " | ||
| 288 | + "it's 3)"}, | ||
| 289 | + TestCase{{29}, "additional info = 29 isn't recognized"}, | ||
| 290 | + TestCase{{1 << 5 | 27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | ||
| 291 | + "Max UINT64 payload is outside the allowed range"}, | ||
| 292 | + TestCase{{1 << 5 | 26, 0xff, 0xff, 0xff, 0xff}, | ||
| 293 | + "Max UINT32 payload is outside the allowed range"}, | ||
| 294 | + TestCase{{1 << 5 | 26, 0x80, 0x00, 0x00, 0x00}, | ||
| 295 | + "UINT32 payload w/ high bit set is outside the allowed range"}, | ||
| 296 | + }}; | ||
| 273 | 297 | for (const TestCase& test : tests) { | |
| 274 | 298 | SCOPED_TRACE(test.msg); | |
| 275 | 299 | CBORTokenizer tokenizer(SpanFrom(test.data)); | |
@@ -1517,6 +1541,22 @@ TEST_F(JsonParserTest, SimpleDictionary) { | |||
| 1517 | 1541 | log_.str()); | |
| 1518 | 1542 | } | |
| 1519 | 1543 | ||
| 1544 | + TEST_F(JsonParserTest, UsAsciiDelCornerCase) { | ||
| 1545 | + // DEL (0x7f) is a 7 bit US-ASCII character, and while it is a control | ||
| 1546 | + // character according to Unicode, it's not considered a control | ||
| 1547 | + // character in https://tools.ietf.org/html/rfc7159#section-7, so | ||
| 1548 | + // it can be placed directly into the JSON string, without JSON escaping. | ||
| 1549 | + std::string json = "{\"foo\": \"a\x7f\"}"; | ||
| 1550 | + ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); | ||
| 1551 | + EXPECT_TRUE(log_.status().ok()); | ||
| 1552 | + EXPECT_EQ( | ||
| 1553 | + "map begin\n" | ||
| 1554 | + "string16: foo\n" | ||
| 1555 | + "string16: a\x7f\n" | ||
| 1556 | + "map end\n", | ||
| 1557 | + log_.str()); | ||
| 1558 | + } | ||
| 1559 | + | ||
| 1520 | 1560 | TEST_F(JsonParserTest, Whitespace) { | |
| 1521 | 1561 | std::string json = "\n {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t"; | |
| 1522 | 1562 | ParseJSON(GetTestPlatform(), SpanFrom(json), &log_); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments