Bug 1032726 part 1 - Make ConvertJSValueToByteString work with Latin1 strings. r=bz,terrence

This commit is contained in:
Jan de Mooij 2014-07-02 13:04:14 +02:00
parent aca5a16c0a
commit adb0b402f0
3 changed files with 64 additions and 14 deletions

View File

@ -2124,30 +2124,51 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
pval.set(JS::StringValue(s)); // Root the new string. pval.set(JS::StringValue(s)); // Root the new string.
} }
// Conversion from Javascript string to ByteString is only valid if all
// characters < 256. This is always the case for Latin1 strings.
size_t length; size_t length;
const jschar *chars = JS_GetStringCharsZAndLength(cx, s, &length); if (!JS_StringHasLatin1Chars(s)) {
// ThrowErrorMessage can GC, so we first scan the string for bad chars
// and report the error outside the AutoCheckCannotGC scope.
bool foundBadChar = false;
size_t badCharIndex;
jschar badChar;
{
JS::AutoCheckCannotGC nogc;
const jschar* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, s, &length);
if (!chars) { if (!chars) {
return false; return false;
} }
// Conversion from Javascript string to ByteString is only valid if all
// characters < 256.
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
if (chars[i] > 255) { if (chars[i] > 255) {
badCharIndex = i;
badChar = chars[i];
foundBadChar = true;
break;
}
}
}
if (foundBadChar) {
MOZ_ASSERT(badCharIndex < length);
MOZ_ASSERT(badChar > 255);
// The largest unsigned 64 bit number (18,446,744,073,709,551,615) has // The largest unsigned 64 bit number (18,446,744,073,709,551,615) has
// 20 digits, plus one more for the null terminator. // 20 digits, plus one more for the null terminator.
char index[21]; char index[21];
static_assert(sizeof(size_t) <= 8, "index array too small"); static_assert(sizeof(size_t) <= 8, "index array too small");
PR_snprintf(index, sizeof(index), "%d", i); PR_snprintf(index, sizeof(index), "%d", badCharIndex);
// A jschar is 16 bits long. The biggest unsigned 16 bit // A jschar is 16 bits long. The biggest unsigned 16 bit
// number (65,535) has 5 digits, plus one more for the null // number (65,535) has 5 digits, plus one more for the null
// terminator. // terminator.
char badChar[6]; char badCharArray[6];
static_assert(sizeof(jschar) <= 2, "badChar array too small"); static_assert(sizeof(jschar) <= 2, "badCharArray too small");
PR_snprintf(badChar, sizeof(badChar), "%d", chars[i]); PR_snprintf(badCharArray, sizeof(badCharArray), "%d", badChar);
ThrowErrorMessage(cx, MSG_INVALID_BYTESTRING, index, badChar); ThrowErrorMessage(cx, MSG_INVALID_BYTESTRING, index, badCharArray);
return false; return false;
} }
} else {
length = JS_GetStringLength(s);
} }
if (length >= UINT32_MAX) { if (length >= UINT32_MAX) {

View File

@ -5321,6 +5321,12 @@ JS_GetStringLength(JSString *str)
return str->length(); return str->length();
} }
JS_PUBLIC_API(bool)
JS_StringHasLatin1Chars(JSString *str)
{
return str->hasLatin1Chars();
}
JS_PUBLIC_API(const jschar *) JS_PUBLIC_API(const jschar *)
JS_GetStringCharsZ(JSContext *cx, JSString *str) JS_GetStringCharsZ(JSContext *cx, JSString *str)
{ {
@ -5359,6 +5365,21 @@ JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *plength)
return linear->chars(); return linear->chars();
} }
JS_PUBLIC_API(const jschar *)
JS_GetTwoByteStringCharsAndLength(JSContext *cx, const JS::AutoCheckCannotGC &nogc, JSString *str,
size_t *plength)
{
JS_ASSERT(plength);
AssertHeapIsIdleOrStringIsFlat(cx, str);
CHECK_REQUEST(cx);
assertSameCompartment(cx, str);
JSLinearString *linear = str->ensureLinear(cx);
if (!linear)
return nullptr;
*plength = linear->length();
return linear->twoByteChars(nogc);
}
JS_PUBLIC_API(const jschar *) JS_PUBLIC_API(const jschar *)
JS_GetInternedStringChars(JSString *str) JS_GetInternedStringChars(JSString *str)
{ {

View File

@ -4166,9 +4166,17 @@ JS_FileEscapedString(FILE *fp, JSString *str, char quote);
extern JS_PUBLIC_API(size_t) extern JS_PUBLIC_API(size_t)
JS_GetStringLength(JSString *str); JS_GetStringLength(JSString *str);
/* Returns true iff the string's characters are stored as Latin1. */
extern JS_PUBLIC_API(bool)
JS_StringHasLatin1Chars(JSString *str);
extern JS_PUBLIC_API(const jschar *) extern JS_PUBLIC_API(const jschar *)
JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *length); JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *length);
extern JS_PUBLIC_API(const jschar *)
JS_GetTwoByteStringCharsAndLength(JSContext *cx, const JS::AutoCheckCannotGC &nogc, JSString *str,
size_t *length);
extern JS_PUBLIC_API(const jschar *) extern JS_PUBLIC_API(const jschar *)
JS_GetInternedStringChars(JSString *str); JS_GetInternedStringChars(JSString *str);