From 54f6a8261578a1b75b7215c81a8d2950732f203d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BF=A0=E9=BD=90?= Date: Tue, 22 Jul 2025 16:38:08 +0800 Subject: [PATCH] fix uaf in OH_JSVM_CloseHandleScope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 王忠齐 --- src/js_native_api_v8.cpp | 1 + src/jsvm_env.h | 27 ++++++++++++++++++++------- test/unittest/test_jsvm.cpp | 22 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/js_native_api_v8.cpp b/src/js_native_api_v8.cpp index 166d472..598daa4 100644 --- a/src/js_native_api_v8.cpp +++ b/src/js_native_api_v8.cpp @@ -4789,6 +4789,7 @@ JSVM_Status OH_JSVM_RetainScript(JSVM_Env env, JSVM_Script script) jsvmData->taggedPointer = v8::Global(env->isolate, jsvmData->ToV8Local(env->isolate)); + env->RetainJsvmData(jsvmData); jsvmData->isGlobal = true; return ClearLastError(env); } diff --git a/src/jsvm_env.h b/src/jsvm_env.h index 7f28702..3032048 100644 --- a/src/jsvm_env.h +++ b/src/jsvm_env.h @@ -16,6 +16,7 @@ #ifndef JSVM_ENV_H #define JSVM_ENV_H #include +#include #include #include @@ -133,25 +134,37 @@ public: template JSVM_Script_Data__* NewJsvmData(T srcPtr, JSVM_Script_Data__::DataType type = JSVM_Script_Data__::kJsvmScript) { - if (dataStack.empty() || openHandleScopes != dataStack.top().first) { - dataStack.emplace(openHandleScopes, std::vector()); + if (dataStack.size() == 0 || openHandleScopes != dataStack.back().first) { + dataStack.emplace_back(openHandleScopes, std::list()); } auto newData = new JSVM_Script_Data__(srcPtr, false, type); - dataStack.top().second.push_back(newData); + dataStack.back().second.push_back(newData); return newData; } void ReleaseJsvmData() { - if (dataStack.empty() || openHandleScopes != dataStack.top().first) { + if (dataStack.size() == 0 || openHandleScopes != dataStack.back().first) { return; } - for (auto data : dataStack.top().second) { + for (auto data : dataStack.back().second) { if (!data->isGlobal) { delete data; } } - dataStack.pop(); + dataStack.pop_back(); + } + + void RetainJsvmData(JSVM_Script_Data__* data) + { + for (auto iter = dataStack.rbegin(); iter != dataStack.rend(); ++iter) { + auto& current = iter->second; + auto globalData = std::find(current.begin(), current.end(), data); + if (globalData != current.end()) { + current.erase(globalData); + break; + } + } } void CreateScopeTracker() @@ -183,7 +196,7 @@ public: JSVM_ExtendedErrorInfo lastError; // Store v8::Data - std::stack>> dataStack; + std::vector>> dataStack; // Store external instance data void* instanceData = nullptr; diff --git a/test/unittest/test_jsvm.cpp b/test/unittest/test_jsvm.cpp index dd8af68..b9876b1 100644 --- a/test/unittest/test_jsvm.cpp +++ b/test/unittest/test_jsvm.cpp @@ -1609,4 +1609,26 @@ HWTEST_F(JSVMTest, test_set_debug_option3, TestSize.Level1) OH_JSVM_CloseHandleScope(env, handleScope); auto status2 = OH_JSVM_SetDebugOption(env, JSVM_SCOPE_CHECK, false); ASSERT_TRUE(status2 == JSVM_OK); +} + +HWTEST_F(JSVMTest, JSVMCloseHandleScopeUAF, TestSize.Level1) +{ + JSVM_HandleScope handle = nullptr; + JSVMTEST_CALL(OH_JSVM_OpenHandleScope(env, &handle)); + + JSVM_Value jsSrc = nullptr; + JSVMTEST_CALL(OH_JSVM_CreateStringUtf8(env, srcProf.c_str(), srcProf.size(), &jsSrc)); + + bool cacheRejected = true; + JSVM_Script script = nullptr; + JSVMTEST_CALL(OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, &cacheRejected, &script)); + + JSVMTEST_CALL(OH_JSVM_RetainScript(env, script)); + JSVMTEST_CALL(OH_JSVM_ReleaseScript(env, script)); + + const int length = 32; + char* data = new((char *)script) char[length]; + memset(data, 0, length); + + JSVMTEST_CALL(OH_JSVM_CloseHandleScope(env, handle)); } \ No newline at end of file -- Gitee