Browse Source

fix: 修复内存执行C函数溢出错误

libffi会对返回值有提升操作, 因此返回值申请内存需要增大

link #9
SongZihuan 4 years ago
parent
commit
235b8632bd
2 changed files with 13 additions and 8 deletions
  1. 7 0
      VirtulMathCore/src/parameter.c
  2. 6 8
      VirtulMathCore/src/runcall.c

+ 7 - 0
VirtulMathCore/src/parameter.c

@@ -977,6 +977,13 @@ bool setArgumentToFFI(ArgumentFFI *af, Argument *arg) {
                             return false;
                     }
                     break;
+                case af_str:
+                    af->arg_v[i] = (double *)memCalloc(1, sizeof(char *));  // af->arg_v是ffi_type **arg_v, 即 *arg_v[]
+                    if (arg->data.value->value->type == V_str) {
+                        *(char **)(af->arg_v[i]) = memWcsToStr(arg->data.value->value->data.str.str, false);
+                    } else
+                        return false;
+                    break;
                 default:
                     return false;
             }

+ 6 - 8
VirtulMathCore/src/runcall.c

@@ -260,17 +260,15 @@ static ResultType callCFunction(LinkValue *function_value, Argument *arg, long i
 
 static bool makeFFIReturn(enum ArgumentFFIType af, void **re_v) {
     switch (af) {
+        case af_char:
         case af_int:
-            *re_v = memCalloc(1, sizeof(int));
+            *re_v = memCalloc(1, sizeof(int64_t));  // 无论是int32或者是int64,都申请int64_t的内存 (否则libffi会提升类型,导致内存溢出)
             break;
         case af_double:
-            *re_v = memCalloc(1, sizeof(double));
+            *re_v = memCalloc(1, sizeof(long double));  // 理由同上
             break;
         case af_str:
-            *re_v = memCalloc(1, sizeof(char *));
-            break;
-        case af_char:
-            *re_v = memCalloc(1, sizeof(char));
+            *re_v = memCalloc(1, sizeof(void *));  // 所有指针数据大小都相同
             break;
         case af_void:
             *re_v = NULL;
@@ -284,10 +282,10 @@ static bool makeFFIReturn(enum ArgumentFFIType af, void **re_v) {
 static bool FFIReturnValue(enum ArgumentFFIType aft, void *re_v, fline line, char *file, FUNC_NT) {
     switch (aft) {  // 应用返回值函数
         case af_int:
-            makeIntValue(*(int *)re_v, line, file, CNEXT_NT);
+            makeIntValue((vint)*(int64_t *)re_v, line, file, CNEXT_NT);  // 先以(int64_t)读取void *类型的数据, 再转换成(vint)类型 (避免大端和小端模式的行为不同)
             break;
         case af_double:
-            makeDouValue(*(double *)re_v, line, file, CNEXT_NT);
+            makeDouValue((vdou)*(long double *)re_v, line, file, CNEXT_NT);
             break;
         case af_str: {
             wchar_t *tmp = memStrToWcs(re_v, false);