|
9 | 9 | #include "../streams/native-stream-source.h" |
10 | 10 |
|
11 | 11 | #include "encode.h" |
| 12 | +#include "jstypes.h" |
12 | 13 | #include "mozilla/Assertions.h" |
13 | 14 | #include "mozilla/ResultVariant.h" |
14 | 15 |
|
@@ -42,6 +43,33 @@ size_t compute_normalized_len(std::string_view src) { |
42 | 43 | return len; |
43 | 44 | } |
44 | 45 |
|
| 46 | +std::optional<size_t> compute_unencoded_normalized_len(JSContext *cx, JS::HandleString value) { |
| 47 | + auto linear = JS_EnsureLinearString(cx, value); |
| 48 | + if (!linear) { |
| 49 | + return std::nullopt; |
| 50 | + } |
| 51 | + auto len = JS::GetDeflatedUTF8StringLength(linear); |
| 52 | + size_t two_byte_length = JS::GetLinearStringLength(linear); |
| 53 | + for (size_t i = 0; i < two_byte_length; i++) { |
| 54 | + char16_t ch = JS::GetLinearStringCharAt(linear, i); |
| 55 | + |
| 56 | + if (ch == CR) { |
| 57 | + if (i+1 < two_byte_length) { |
| 58 | + char16_t next = JS::GetLinearStringCharAt(linear, i+1); |
| 59 | + if (next == LF) { |
| 60 | + i += 1; |
| 61 | + // the character is already accounted for |
| 62 | + continue; |
| 63 | + } |
| 64 | + } |
| 65 | + len += 1; |
| 66 | + } else if (ch == LF) { |
| 67 | + len += 1; // CRLF |
| 68 | + } |
| 69 | + } |
| 70 | + return len; |
| 71 | +} |
| 72 | + |
45 | 73 | // Normalizes newlines in a string by replacing: |
46 | 74 | // - CR not followed by LF -> CRLF |
47 | 75 | // - LF not preceded by CR -> CRLF |
@@ -517,12 +545,15 @@ mozilla::Result<size_t, OutOfMemory> MultipartFormDataImpl::query_length(JSConte |
517 | 545 | total += 2 * crlf_len; |
518 | 546 |
|
519 | 547 | RootedValue value_str(cx, entry.value); |
520 | | - auto value = core::encode(cx, value_str); |
| 548 | + JS::RootedString value(cx, JS::ToString(cx, value_str)); |
521 | 549 | if (!value) { |
522 | 550 | return mozilla::Result<size_t, OutOfMemory>(OutOfMemory {}); |
523 | 551 | } |
524 | | - |
525 | | - total += compute_normalized_len(value); |
| 552 | + auto value_len = compute_unencoded_normalized_len(cx, value); |
| 553 | + if (!value_len.has_value()) { |
| 554 | + return mozilla::Result<size_t, OutOfMemory>(OutOfMemory {}); |
| 555 | + } |
| 556 | + total += value_len.value(); |
526 | 557 | } else { |
527 | 558 | MOZ_ASSERT(File::is_instance(entry.value)); |
528 | 559 | RootedObject obj(cx, &entry.value.toObject()); |
|
0 commit comments