diff --git a/js/public/CharacterEncoding.h b/js/public/CharacterEncoding.h index 21aabbc1206f..c9cc616901b7 100644 --- a/js/public/CharacterEncoding.h +++ b/js/public/CharacterEncoding.h @@ -127,6 +127,9 @@ class ConstUTF8CharsZ : data_(aBytes) { MOZ_ASSERT(aBytes[aLength] == '\0'); +#ifdef DEBUG + validate(aLength); +#endif } const void* get() const { return data_; } @@ -134,6 +137,11 @@ class ConstUTF8CharsZ const char* c_str() const { return data_; } explicit operator bool() const { return data_ != nullptr; } + + private: +#ifdef DEBUG + void validate(size_t aLength); +#endif }; /* diff --git a/js/src/vm/CharacterEncoding.cpp b/js/src/vm/CharacterEncoding.cpp index bc9d0d17f786..401aff6be91a 100644 --- a/js/src/vm/CharacterEncoding.cpp +++ b/js/src/vm/CharacterEncoding.cpp @@ -249,6 +249,7 @@ ReportTooBigCharacter(JSContext* cx, uint32_t v) enum InflateUTF8Action { CountAndReportInvalids, CountAndIgnoreInvalids, + AssertNoInvalids, Copy }; @@ -261,7 +262,8 @@ static bool InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, size_t* dstlenp, bool* isAsciip) { - *isAsciip = true; + if (Action != AssertNoInvalids) + *isAsciip = true; // Count how many char16_t characters need to be in the inflated string. // |i| is the index into |src|, and |j| is the the index into |dst|. @@ -276,7 +278,8 @@ InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, siz } else { // Non-ASCII code unit. Determine its length in bytes (n). - *isAsciip = false; + if (Action != AssertNoInvalids) + *isAsciip = false; uint32_t n = 1; while (v & (0x80 >> n)) n++; @@ -286,6 +289,8 @@ InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, siz if (Action == CountAndReportInvalids) { \ report(cx, arg); \ return false; \ + } else if (Action == AssertNoInvalids) { \ + MOZ_CRASH("invalid UTF-8 string: " # report); \ } else { \ if (Action == Copy) \ dst[j] = char16_t(REPLACE_UTF8); \ @@ -350,7 +355,8 @@ InflateUTF8StringToBuffer(JSContext* cx, const UTF8Chars src, char16_t* dst, siz } } - *dstlenp = j; + if (Action != AssertNoInvalids) + *dstlenp = j; return true; } @@ -398,3 +404,12 @@ JS::LossyUTF8CharsToNewTwoByteCharsZ(JSContext* cx, const UTF8Chars utf8, size_t return InflateUTF8StringHelper(cx, utf8, outlen); } +#ifdef DEBUG +void +JS::ConstUTF8CharsZ::validate(size_t aLength) +{ + MOZ_ASSERT(data_); + UTF8Chars chars(data_, aLength); + InflateUTF8StringToBuffer(nullptr, chars, nullptr, nullptr, nullptr); +} +#endif