Ignore:
Timestamp:
Jul 14, 2021, 12:15:56 PM (4 years ago)
Author:
[email protected]
Message:

Check for out of memory in JSC::globalFuncEscape() and JSC::globalFuncUnescape().
https://bugs.webkit.org/show_bug.cgi?id=227962
rdar://78392251

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/out-of-memory-in-globalFuncUnescape.js: Added.

Source/JavaScriptCore:

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r278253 r279915  
    578578JSC_DEFINE_HOST_FUNCTION(globalFuncEscape, (JSGlobalObject* globalObject, CallFrame* callFrame))
    579579{
    580     return JSValue::encode(toStringView(globalObject, callFrame->argument(0), [&] (StringView view) {
     580    return JSValue::encode(toStringView(globalObject, callFrame->argument(0), [&] (StringView view) -> JSString* {
    581581        static const Bitmap<256> doNotEscape = makeCharacterBitmap(
    582582            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     
    587587
    588588        VM& vm = globalObject->vm();
    589         StringBuilder builder;
     589        auto scope = DECLARE_THROW_SCOPE(vm);
     590
     591        StringBuilder builder(StringBuilder::OverflowHandler::RecordOverflow);
    590592        if (view.is8Bit()) {
    591593            const LChar* c = view.characters8();
     
    597599                    builder.append('%', hex(u, 2));
    598600            }
    599             return jsString(vm, builder.toString());
    600         }
    601 
    602         const UChar* c = view.characters16();
    603         for (unsigned k = 0; k < view.length(); k++, c++) {
    604             UChar u = c[0];
    605             if (u >= doNotEscape.size())
    606                 builder.append("%u", hex(static_cast<uint8_t>(u >> 8), 2), hex(static_cast<uint8_t>(u), 2));
    607             else if (doNotEscape.get(static_cast<LChar>(u)))
    608                 builder.append(*c);
    609             else
    610                 builder.append('%', hex(u, 2));
    611         }
    612 
     601        } else {
     602            const UChar* c = view.characters16();
     603            for (unsigned k = 0; k < view.length(); k++, c++) {
     604                UChar u = c[0];
     605                if (u >= doNotEscape.size())
     606                    builder.append("%u", hex(static_cast<uint8_t>(u >> 8), 2), hex(static_cast<uint8_t>(u), 2));
     607                else if (doNotEscape.get(static_cast<LChar>(u)))
     608                    builder.append(*c);
     609                else
     610                    builder.append('%', hex(u, 2));
     611            }
     612        }
     613
     614        if (UNLIKELY(builder.hasOverflowed())) {
     615            throwOutOfMemoryError(globalObject, scope);
     616            return { };
     617        }
    613618        return jsString(vm, builder.toString());
    614619    }));
     
    617622JSC_DEFINE_HOST_FUNCTION(globalFuncUnescape, (JSGlobalObject* globalObject, CallFrame* callFrame))
    618623{
    619     return JSValue::encode(toStringView(globalObject, callFrame->argument(0), [&] (StringView view) {
     624    return JSValue::encode(toStringView(globalObject, callFrame->argument(0), [&] (StringView view) -> JSString* {
    620625        // We use int for k and length intentionally since we would like to evaluate
    621626        // the condition `k <= length -6` even if length is less than 6.
     
    623628        int length = view.length();
    624629
    625         StringBuilder builder;
     630        VM& vm = globalObject->vm();
     631        auto scope = DECLARE_THROW_SCOPE(vm);
     632
     633        StringBuilder builder(StringBuilder::OverflowHandler::RecordOverflow);
    626634        builder.reserveCapacity(length);
    627635
     
    667675        }
    668676
    669         return jsString(globalObject->vm(), builder.toString());
     677        if (UNLIKELY(builder.hasOverflowed())) {
     678            throwOutOfMemoryError(globalObject, scope);
     679            return { };
     680        }
     681        return jsString(vm, builder.toString());
    670682    }));
    671683}
Note: See TracChangeset for help on using the changeset viewer.