已合并
[ani] correct signatures with any type #78553
[ani] correct signatures with any type #78553
已合并
slynkodenis创建于 2025年12月30日
共 8 个文件变更+37-37
@@ -497,7 +497,7 @@ bool ParseDragMixParam(ani_env* env, ArkUIDragControllerAsync& asyncCtx, ani_obj
497 for (int32_t i = 0; i < builderArrayLengthInt; i++) {497 for (int32_t i = 0; i < builderArrayLengthInt; i++) {
498 ani_ref itemRef;498 ani_ref itemRef;
499 if ((status = env->Object_CallMethodByName_Ref(static_cast<ani_object>(builderObj), "$_get",499 if ((status = env->Object_CallMethodByName_Ref(static_cast<ani_object>(builderObj), "$_get",
500- "i:C{std.core.Object}", &itemRef, (ani_int)i)) != ANI_OK) {500+ "i:Y", &itemRef, (ani_int)i)) != ANI_OK) {
501 HILOGE("AceDrag, get builder node from array fail. status = %{public}d", status);501 HILOGE("AceDrag, get builder node from array fail. status = %{public}d", status);
502 isParseSucess = false;502 isParseSucess = false;
503 break;503 break;
@@ -518,7 +518,7 @@ bool ParseDragMixParam(ani_env* env, ArkUIDragControllerAsync& asyncCtx, ani_obj
518 for (int32_t i = 0; i < dragItemInfoArrayLengthInt; i++) {518 for (int32_t i = 0; i < dragItemInfoArrayLengthInt; i++) {
519 ani_ref itemRef;519 ani_ref itemRef;
520 if ((status = env->Object_CallMethodByName_Ref(520 if ((status = env->Object_CallMethodByName_Ref(
521- dragItemInfo, "$_get", "i:C{std.core.Object}", &itemRef, (ani_int)i)) != ANI_OK) {521+ dragItemInfo, "$_get", "i:Y", &itemRef, (ani_int)i)) != ANI_OK) {
522 HILOGE("AceDrag, get dragItemInfo from array fail. status = %{public}d", status);522 HILOGE("AceDrag, get dragItemInfo from array fail. status = %{public}d", status);
523 isParseSucess = false;523 isParseSucess = false;
524 break;524 break;
@@ -701,7 +701,7 @@ bool CheckAndParseSecondParams(ani_env* env, ArkUIDragControllerAsync& asyncCtx,
701 } else {701 } else {
702 asyncCtx.touchPoint = SharedPointerWrapper(nullptr);702 asyncCtx.touchPoint = SharedPointerWrapper(nullptr);
703 }703 }
704- 704+ 
705 if (!ParsePreviewOptions(env, asyncCtx, static_cast<ani_object>(previewOptionsAni))) {705 if (!ParsePreviewOptions(env, asyncCtx, static_cast<ani_object>(previewOptionsAni))) {
706 HILOGE("AceDrag, parse previewOptions failed.");706 HILOGE("AceDrag, parse previewOptions failed.");
707 return false;707 return false;
@@ -203,7 +203,7 @@ std::string GetAniStringEnum(ani_env* env, ani_array array, ani_int index, bool&
203{203{
204 ani_ref modeRef;204 ani_ref modeRef;
205 if (ANI_OK != env->Object_CallMethodByName_Ref(205 if (ANI_OK != env->Object_CallMethodByName_Ref(
206- array, "$_get", "i:C{std.core.Object}", &modeRef, index)) {206+ array, "$_get", "i:Y", &modeRef, index)) {
207 isSuccess = false;207 isSuccess = false;
208 return "";208 return "";
209 }209 }
@@ -393,7 +393,7 @@ bool ParseDragPreviewMode(ani_env* env, ArkUIDragPreviewOption& previewOptions,
393 for (int32_t i = 0; i < lengthInt; i++) {393 for (int32_t i = 0; i < lengthInt; i++) {
arkui-feature-manager
arkui-feature-managerarkui-feature-manager2025年12月30日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🔴 不安全的any类型到ani_object的类型转换

位置: L393-L399 | 严重程度: Critical

❓ 问题描述

代码通过"i:Y"签名从数组中获取一个any类型的元素(modeRef),但未进行任何类型检查,直接将其static_cast为ani_object并传递给AniUtils::IsUndefined。如果该any值实际上不是对象(例如,它是一个数字或字符串),此转换会导致未定义行为,可能造成内存访问错误。修改后的签名明确指出类型是any,因此调用方必须进行防御性类型检查。

💡 修复建议

修改建议:在进行类型转换和调用相关函数之前,使用env->GetValueType验证modeRef的类型是否为ANI_VALUE_TYPE_OBJECT。如果类型不匹配,应记录错误并提前返回,以防止未定义行为。

393: for (int32_t i = 0; i < lengthInt; i++) { 394: ani_ref modeRef; 395: if (ANI_OK != env->Object_CallMethodByName_Ref( 396: modeObj, "$_get", "i:Y", &modeRef, (ani_int)i)) { 397: return false; 398: } 399: ani_value_type valueType; 400: if (env->GetValueType(modeRef, &valueType) != ANI_OK || valueType != ANI_VALUE_TYPE_OBJECT) { 401: HILOGE("AceDrag, modeRef is not an object, type: %{public}d", valueType); 402: return false; 403: }


likedislike
rokashevichsvetlana
rokashevichsvetlana
1月12日 评论:
394 ani_ref modeRef;394 ani_ref modeRef;
395 if (ANI_OK != env->Object_CallMethodByName_Ref(395 if (ANI_OK != env->Object_CallMethodByName_Ref(
396- modeObj, "$_get", "i:C{std.core.Object}", &modeRef, (ani_int)i)) {396+ modeObj, "$_get", "i:Y", &modeRef, (ani_int)i)) {
397 return false;397 return false;
398 }398 }
399 if (AniUtils::IsUndefined(env, static_cast<ani_object>(modeRef))) {399 if (AniUtils::IsUndefined(env, static_cast<ani_object>(modeRef))) {
@@ -20,13 +20,13 @@ import { int32 } from '@koalaui/common';
20import { __context, __id, GlobalStateManager, IncrementalNode, memoEntry, memoEntry1, mutableState, MutableState, NodeAttach } from '@koalaui/runtime';20import { __context, __id, GlobalStateManager, IncrementalNode, memoEntry, memoEntry1, mutableState, MutableState, NodeAttach } from '@koalaui/runtime';
21import { StateContext } from 'arkui.incremental.runtime.state';21import { StateContext } from 'arkui.incremental.runtime.state';
22import { ExtendableComponent } from './extendableComponent';22import { ExtendableComponent } from './extendableComponent';
23-import { 23+import {
24- StateDecoratedVariable, 24+ StateDecoratedVariable,
25- ProvideDecoratedVariable, 25+ ProvideDecoratedVariable,
26 PropDecoratedVariable,26 PropDecoratedVariable,
27 PropRefDecoratedVariable,27 PropRefDecoratedVariable,
28- LinkDecoratedVariable, 28+ LinkDecoratedVariable,
29- ConsumeDecoratedVariable, 29+ ConsumeDecoratedVariable,
30 InteropWatchFunc,30 InteropWatchFunc,
31 uiUtils,31 uiUtils,
32 IObservedObject,32 IObservedObject,
@@ -134,7 +134,7 @@ export function compatibleStaticComponent<T extends BaseCustomComponent<T_Option
134 const manager = GlobalStateManager.instance;134 const manager = GlobalStateManager.instance;
135 135 
136 ArkThemeScopeManager.getInstance().applyColorModeFromThemeScope();136 ArkThemeScopeManager.getInstance().applyColorModeFromThemeScope();
137- 137+ 
138 const node = manager.updatableNode(new IncrementalNode(), (context: StateContext) => {138 const node = manager.updatableNode(new IncrementalNode(), (context: StateContext) => {
139 ArkUIAniModule._Common_Sync_InstanceId(uiContext.getInstanceId());139 ArkUIAniModule._Common_Sync_InstanceId(uiContext.getInstanceId());
140 let r = OBSERVE.renderingComponent;140 let r = OBSERVE.renderingComponent;
@@ -159,7 +159,7 @@ export function compatibleStaticComponent<T extends BaseCustomComponent<T_Option
159 () => {159 () => {
160 ArkThemeScopeManager.getInstance().executeReload(node);160 ArkThemeScopeManager.getInstance().executeReload(node);
161 (staticComponent as CustomDelegate<T, T_Options>).__updateStruct(options ? options() : undefined);161 (staticComponent as CustomDelegate<T, T_Options>).__updateStruct(options ? options() : undefined);
162- }, 162+ },
163 peerNode.getPeerPtr() as number,163 peerNode.getPeerPtr() as number,
164 ];164 ];
165}165}
@@ -318,13 +318,13 @@ export function isDynamicObject<T>(value: T): boolean {
318export function getRawObject<T>(value: T): T {318export function getRawObject<T>(value: T): T {
319 const global = ESValue.getGlobal();319 const global = ESValue.getGlobal();
320 const getRawObjectForInterop = global.getProperty('getRawObjectForInterop');320 const getRawObjectForInterop = global.getProperty('getRawObjectForInterop');
321- return getRawObjectForInterop.invoke(ESValue.wrap(value)).unwrap()! as Object as T;321+ return getRawObjectForInterop.invoke(ESValue.wrap(value)).unwrap() as T;
322}322}
323 323 
324export function getObservedObject<T>(value: T): T {324export function getObservedObject<T>(value: T): T {
325 const global = ESValue.getGlobal();325 const global = ESValue.getGlobal();
326 const createObservedObject = global.getProperty('createObservedObject');326 const createObservedObject = global.getProperty('createObservedObject');
327- return createObservedObject.invoke(ESValue.wrap(value)).unwrap()! as Object as T;327+ return createObservedObject.invoke(ESValue.wrap(value)).unwrap() as T;
328}328}
329 329 
330export function registerCreateWatchFuncCallback(): void {330export function registerCreateWatchFuncCallback(): void {
@@ -410,17 +410,17 @@ export function compatibleWrappedBuilderInternal(builder: Any, ...args: FixedArr
410 break;410 break;
411 case 3:411 case 3:
412 createCompatibleNode = global.getProperty('createCompatibleNodeWithFunc3');412 createCompatibleNode = global.getProperty('createCompatibleNodeWithFunc3');
413- component = createCompatibleNode.invoke(ESValue.wrap(builder), elmtId, args[0], 413+ component = createCompatibleNode.invoke(ESValue.wrap(builder), elmtId, args[0],
414 args[1], args[2]);414 args[1], args[2]);
415 break;415 break;
416 case 4:416 case 4:
417 createCompatibleNode = global.getProperty('createCompatibleNodeWithFunc4');417 createCompatibleNode = global.getProperty('createCompatibleNodeWithFunc4');
418- component = createCompatibleNode.invoke(ESValue.wrap(builder), elmtId, args[0], 418+ component = createCompatibleNode.invoke(ESValue.wrap(builder), elmtId, args[0],
419 args[1], args[2], args[3]);419 args[1], args[2], args[3]);
420 break;420 break;
421 case 5:421 case 5:
422 createCompatibleNode = global.getProperty('createCompatibleNodeWithFunc5');422 createCompatibleNode = global.getProperty('createCompatibleNodeWithFunc5');
423- component = createCompatibleNode.invoke(ESValue.wrap(builder), elmtId, args[0], 423+ component = createCompatibleNode.invoke(ESValue.wrap(builder), elmtId, args[0],
424 args[1], args[2], args[3], args[4]);424 args[1], args[2], args[3], args[4]);
425 break;425 break;
426 case 6:426 case 6:
@@ -638,7 +638,7 @@ function parseInfoFromJsonElement(infoElement: jsonx.JsonElement): NavPathInfo |
638 let paramObj: Object | undefined = infoElement.tryGetElement('param');638 let paramObj: Object | undefined = infoElement.tryGetElement('param');
639 let isEntry: boolean | undefined = infoElement.tryGetBoolean('isEntry');639 let isEntry: boolean | undefined = infoElement.tryGetBoolean('isEntry');
640 return new NavPathInfo(name, paramObj, undefined, isEntry);640 return new NavPathInfo(name, paramObj, undefined, isEntry);
641-} 641+}
642 642 
643function parseNumberArrayFromJson(jsonArray: string): Array<int32> {643function parseNumberArrayFromJson(jsonArray: string): Array<int32> {
644 let array = new Array<int32>();644 let array = new Array<int32>();
@@ -1001,7 +1001,7 @@ function transferCompatibleDynamicBuilder(builder: (...args: FixedArray<Any>) =>
1001 return (1001 return (
1002 /** @memo */1002 /** @memo */
1003 (...args: FixedArray<Any>) => {1003 (...args: FixedArray<Any>) => {
1004- let argsESValue: FixedArray<ESValueOrUndefined> = new ESValueOrUndefined[args.length]; 1004+ let argsESValue: FixedArray<ESValueOrUndefined> = new ESValueOrUndefined[args.length];
1005 for (let i = 0; i < args.length; i++) {1005 for (let i = 0; i < args.length; i++) {
1006 if (args[i] instanceof ESValue) {1006 if (args[i] instanceof ESValue) {
1007 argsESValue[i] = args[i] as ESValue;1007 argsESValue[i] = args[i] as ESValue;
@@ -1067,7 +1067,7 @@ export function enableCompatibleObservedV2ForStatic<T>(
1067 let recordStaticState = (value: MutableState<int32>) => {1067 let recordStaticState = (value: MutableState<int32>) => {
1068 value.value1068 value.value
1069 }1069 }
1070- let updateStaticState = (value: MutableState<int32>) => { 1070+ let updateStaticState = (value: MutableState<int32>) => {
1071 value.value++1071 value.value++
1072 ESValue.getGlobal().getProperty('runPendingJobs').invoke();1072 ESValue.getGlobal().getProperty('runPendingJobs').invoke();
1073 }1073 }
@@ -230,7 +230,7 @@ bool GetArrayIntParam(ani_env* env, ani_ref ref, std::vector<int32_t>& result)
230 for (size_t i = 0; i < length; i++) {230 for (size_t i = 0; i < length; i++) {
231 ani_ref itemRef;231 ani_ref itemRef;
232 status = env->Object_CallMethodByName_Ref(232 status = env->Object_CallMethodByName_Ref(
233- static_cast<ani_object>(arrayObj), "$_get", "i:C{std.core.Object}", &itemRef, (ani_int)i);233+ static_cast<ani_object>(arrayObj), "$_get", "i:Y", &itemRef, (ani_int)i);
234 if (status != ANI_OK) {234 if (status != ANI_OK) {
235 return false;235 return false;
236 }236 }
@@ -328,7 +328,7 @@ void ProcessResourceType(ani_env* env, ani_object value, ani_ref paramsRef, ani_
328 std::vector<std::string> stringArray;328 std::vector<std::string> stringArray;
329 for (int i = 0; i < int(length); i++) {329 for (int i = 0; i < int(length); i++) {
330 ani_ref itemRef;330 ani_ref itemRef;
331- status = env->Object_CallMethodByName_Ref(paramsObj, "$_get", "i:C{std.core.Object}", &itemRef, (ani_int)i);331+ status = env->Object_CallMethodByName_Ref(paramsObj, "$_get", "i:Y", &itemRef, (ani_int)i);
332 if (status != ANI_OK) {332 if (status != ANI_OK) {
333 continue;333 continue;
334 }334 }
@@ -352,7 +352,7 @@ void ProcessResourceType(ani_env* env, ani_object value, ani_ref paramsRef, ani_
352 ani_string firstStr;352 ani_string firstStr;
353 status = env->String_NewUTF8(resName.c_str(), resName.size(), &firstStr);353 status = env->String_NewUTF8(resName.c_str(), resName.size(), &firstStr);
354 if (status != ANI_OK) {354 if (status != ANI_OK) {
355- status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iC{std.core.Object}:", index, firstStr);355+ status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iY:", index, firstStr);
356 if (status != ANI_OK) {356 if (status != ANI_OK) {
357 return;357 return;
358 }358 }
@@ -366,7 +366,7 @@ void ProcessResourceType(ani_env* env, ani_object value, ani_ref paramsRef, ani_
366 break;366 break;
367 }367 }
368 368 
369- status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iC{std.core.Object}:", index, aniStr);369+ status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iY:", index, aniStr);
370 if (status != ANI_OK) {370 if (status != ANI_OK) {
371 break;371 break;
372 }372 }
@@ -37,7 +37,7 @@ namespace OHOS::Ace::Ani {
37namespace {37namespace {
38constexpr char PIXEL_MAP_CONSTRUCTOR[] = "C{@ohos.multimedia.image.image.PixelMap}:";38constexpr char PIXEL_MAP_CONSTRUCTOR[] = "C{@ohos.multimedia.image.image.PixelMap}:";
39constexpr char PIXEL_MAP_DRAWABLE[] = "@ohos.arkui.drawableDescriptor.PixelMapDrawableDescriptor";39constexpr char PIXEL_MAP_DRAWABLE[] = "@ohos.arkui.drawableDescriptor.PixelMapDrawableDescriptor";
40-constexpr char ARRAY_GET[] = "i:C{std.core.Object}";40+constexpr char ARRAY_GET[] = "i:Y";
41constexpr char ANIMATED_CONSTRUCTOR[] = "C{std.core.Array}C{@ohos.arkui.drawableDescriptor.AnimationOptions}:";41constexpr char ANIMATED_CONSTRUCTOR[] = "C{std.core.Array}C{@ohos.arkui.drawableDescriptor.AnimationOptions}:";
42constexpr char ANIMATED_DRAWABLE[] = "@ohos.arkui.drawableDescriptor.AnimatedDrawableDescriptor";42constexpr char ANIMATED_DRAWABLE[] = "@ohos.arkui.drawableDescriptor.AnimatedDrawableDescriptor";
43constexpr char LAYERED_CONSTRUCTOR[] =43constexpr char LAYERED_CONSTRUCTOR[] =
@@ -142,7 +142,7 @@ ani_method GetOrCreateArrayGetMethod(ani_env* env)
142 }142 }
143 143 
144 ani_method result;144 ani_method result;
145- if (ANI_OK != env->Class_FindMethod(arrayClass, "$_get", "i:C{std.core.Object}", &result)) {145+ if (ANI_OK != env->Class_FindMethod(arrayClass, "$_get", "i:Y", &result)) {
146 return nullptr;146 return nullptr;
147 }147 }
148 148 
@@ -610,7 +610,7 @@ void ProcessResourceType(ani_env *env, ani_object value, ani_ref paramsRef, ani_
610 std::vector<std::string> stringArray;610 std::vector<std::string> stringArray;
611 for (int i = 0; i < int(length); i++) {611 for (int i = 0; i < int(length); i++) {
612 ani_ref itemRef;612 ani_ref itemRef;
613- status = env->Object_CallMethodByName_Ref(paramsObj, "$_get", "i:C{std.core.Object}", &itemRef, (ani_int)i);613+ status = env->Object_CallMethodByName_Ref(paramsObj, "$_get", "i:Y", &itemRef, (ani_int)i);
614 if (status != ANI_OK) {614 if (status != ANI_OK) {
615 continue;615 continue;
616 }616 }
@@ -634,7 +634,7 @@ void ProcessResourceType(ani_env *env, ani_object value, ani_ref paramsRef, ani_
634 ani_string firstStr;634 ani_string firstStr;
635 status = env->String_NewUTF8(resName.c_str(), resName.size(), &firstStr);635 status = env->String_NewUTF8(resName.c_str(), resName.size(), &firstStr);
636 if (status != ANI_OK) {636 if (status != ANI_OK) {
637- status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iC{std.core.Object}:", index, firstStr);637+ status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iY:", index, firstStr);
638 if (status != ANI_OK) {638 if (status != ANI_OK) {
639 return;639 return;
640 }640 }
@@ -648,7 +648,7 @@ void ProcessResourceType(ani_env *env, ani_object value, ani_ref paramsRef, ani_
648 break;648 break;
649 }649 }
650 650 
651- status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iC{std.core.Object}:", index, aniStr);651+ status = env->Object_CallMethodByName_Void(paramsObj, "$_set", "iY:", index, aniStr);
652 if (status != ANI_OK) {652 if (status != ANI_OK) {
653 break;653 break;
654 }654 }
@@ -105,7 +105,7 @@ void processResourceType(ani_env *env, ani_object value, ani_ref params_ref, siz
105 for (int i = 0; i < int(length); i++) {105 for (int i = 0; i < int(length); i++) {
106 ani_ref stringEntryRef;106 ani_ref stringEntryRef;
107 if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast<ani_object>(params_ref),107 if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast<ani_object>(params_ref),
108- "$_get", "i:C{std.core.Object}", &stringEntryRef, (ani_int)i)) {108+ "$_get", "i:Y", &stringEntryRef, (ani_int)i)) {
109 break;109 break;
110 }110 }
111 auto stringContent = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(stringEntryRef));111 auto stringContent = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(stringEntryRef));
@@ -123,7 +123,7 @@ void processResourceType(ani_env *env, ani_object value, ani_ref params_ref, siz
123 ani_string ani_first_str;123 ani_string ani_first_str;
124 if (ANI_OK == env->String_NewUTF8(resName.c_str(), resName.size(), &ani_first_str)) {124 if (ANI_OK == env->String_NewUTF8(resName.c_str(), resName.size(), &ani_first_str)) {
125 if (ANI_OK != env->Object_CallMethodByName_Void(static_cast<ani_object>(params_ref),125 if (ANI_OK != env->Object_CallMethodByName_Void(static_cast<ani_object>(params_ref),
126- "$_set", "iC{std.core.Object}:", index, ani_first_str)) {126+ "$_set", "iY:", index, ani_first_str)) {
127 return;127 return;
128 }128 }
129 }129 }
@@ -134,7 +134,7 @@ void processResourceType(ani_env *env, ani_object value, ani_ref params_ref, siz
134 break;134 break;
135 }135 }
136 if (ANI_OK != env->Object_CallMethodByName_Void(static_cast<ani_object>(params_ref),136 if (ANI_OK != env->Object_CallMethodByName_Void(static_cast<ani_object>(params_ref),
137- "$_set", "iC{std.core.Object}:", index, ani_str)) {137+ "$_set", "iY:", index, ani_str)) {
138 break;138 break;
139 }139 }
140 index++;140 index++;
@@ -234,7 +234,7 @@ void CompleteResourceParamV2(ani_env *env, ani_object value)
234 return;234 return;
235 }235 }
236 int32_t aniType = static_cast<int32_t>(resType);236 int32_t aniType = static_cast<int32_t>(resType);
237- 237+ 
238 if (ANI_OK != env->Object_SetPropertyByName_Int(value, "type", static_cast<ani_int>(aniType))) {238 if (ANI_OK != env->Object_SetPropertyByName_Int(value, "type", static_cast<ani_int>(aniType))) {
239 return;239 return;
240 }240 }
@@ -324,13 +324,13 @@ std::string ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str)
324{324{
arkui-feature-managerarkui-feature-manager
arkui-feature-managerarkui-feature-manager2025年12月30日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🟡 脆弱的ANI字符串到std::string的转换逻辑

位置: L324-L336 | 严重程度: Medium

❓ 问题描述

函数ANIUtils_ANIStringToStdString在获取字符串后,手动在buffer[bytesWritten]位置写入'\0'。这种做法存在风险:bytesWritten的值依赖于ANI运行时的具体实现(可能包含也可能不包含终止符),如果它等于字符串长度,此操作会覆盖运行时已写入的终止符;如果它包含终止符长度,此操作会导致缓冲区溢出。这种模糊性使得代码脆弱且依赖于实现细节。

💡 修复建议

修改建议:使用std::string的构造函数和resize方法进行更安全的字符串转换,避免手动管理C风格字符缓冲区,从而消除潜在的越界风险。

324: std::string ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str) 325: { 326: ani_size strSize = 0; 327: if (env->String_GetUTF8Size(ani_str, &strSize) != ANI_OK) { 328: return ""; 329: } 330: std::string result(strSize, '\0'); 331: ani_size bytesWritten = 0; 332: if (env->String_GetUTF8(ani_str, result.data(), strSize + 1, &bytesWritten) != ANI_OK) { 333: return ""; 334: } 335: result.resize(bytesWritten); 336: return result;


likedislike
rokashevichsvetlana
rokashevichsvetlana
1月12日 评论:
arkui-feature-managerarkui-feature-manager2025年12月30日

🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)


🟡 脆弱的ANI字符串到std::string的转换逻辑

位置: L324-L336 | 严重程度: Medium

❓ 问题描述

函数ANIUtils_ANIStringToStdString在获取字符串后,手动在buffer[bytesWritten]位置写入'\0'。这种做法存在风险:bytesWritten的值依赖于ANI运行时的具体实现(可能包含也可能不包含终止符),如果它等于字符串长度,此操作会覆盖运行时已写入的终止符;如果它包含终止符长度,此操作会导致缓冲区溢出。这种模糊性使得代码脆弱且依赖于实现细节。

💡 修复建议

修改建议:使用std::string的构造函数和resize方法进行更安全的字符串转换,避免手动管理C风格字符缓冲区,从而消除潜在的越界风险。

324: std::string ANIUtils_ANIStringToStdString(ani_env *env, ani_string ani_str) 325: { 326: ani_size strSize = 0; 327: if (env->String_GetUTF8Size(ani_str, &strSize) != ANI_OK) { 328: return ""; 329: } 330: std::string result(strSize, '\0'); 331: ani_size bytesWritten = 0; 332: if (env->String_GetUTF8(ani_str, result.data(), strSize + 1, &bytesWritten) != ANI_OK) { 333: return ""; 334: } 335: result.resize(bytesWritten); 336: return result;


likedislike
rokashevichsvetlana
rokashevichsvetlana
1月12日 评论:
325 ani_size strSize;325 ani_size strSize;
326 env->String_GetUTF8Size(ani_str, &strSize);326 env->String_GetUTF8Size(ani_str, &strSize);
327- 327+ 
328 std::vector<char> buffer(strSize + 1);328 std::vector<char> buffer(strSize + 1);
329 char* utf8Buffer = buffer.data();329 char* utf8Buffer = buffer.data();
330 330 
331 ani_size bytesWritten = 0;331 ani_size bytesWritten = 0;
332 env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytesWritten);332 env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytesWritten);
333- 333+ 
334 utf8Buffer[bytesWritten] = '\0';334 utf8Buffer[bytesWritten] = '\0';
335 std::string content = std::string(utf8Buffer);335 std::string content = std::string(utf8Buffer);
336 return content;336 return content;
@@ -493,7 +493,7 @@ bool ParseResourceParamName(ani_env *env, ani_object objects, ResourceInfo& info
493 for (int i = 0; i < int(length); i++) {493 for (int i = 0; i < int(length); i++) {
494 ani_ref stringEntryRef;494 ani_ref stringEntryRef;
495 if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast<ani_object>(params_ref),495 if (ANI_OK != env->Object_CallMethodByName_Ref(static_cast<ani_object>(params_ref),
496- "$_get", "i:C{std.core.Object}", &stringEntryRef, (ani_int)i)) {496+ "$_get", "i:Y", &stringEntryRef, (ani_int)i)) {
497 return false;497 return false;
498 }498 }
499 strings.emplace_back(ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(stringEntryRef)));499 strings.emplace_back(ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(stringEntryRef)));
@@ -885,7 +885,7 @@ void ParseArray([[maybe_unused]] ani_env* env,
885 for (int i = 0; i < static_cast<int32_t>(length); i++) {885 for (int i = 0; i < static_cast<int32_t>(length); i++) {
886 ani_ref pointRef;886 ani_ref pointRef;
887 if (ANI_OK != env->Object_CallMethodByName_Ref(887 if (ANI_OK != env->Object_CallMethodByName_Ref(
888- static_cast<ani_object>(options), "$_get", "i:C{std.core.Object}", &pointRef, (ani_int)i)) {888+ static_cast<ani_object>(options), "$_get", "i:Y", &pointRef, (ani_int)i)) {
889 break;889 break;
890 }890 }
891 OHOS::Ace::CalcDimension result;891 OHOS::Ace::CalcDimension result;