浏览代码

feat: 添加code结构体语义检查函数

SongZihuan 3 年之前
父节点
当前提交
dbcf4f11dc
共有 5 个文件被更改,包括 51 次插入7 次删除
  1. 1 0
      include/core/code.h
  2. 1 2
      src/core/bytecode.c
  3. 46 1
      src/core/code.c
  4. 3 3
      src/core/run.c
  5. 0 1
      src/runtime/aFunlang.c

+ 1 - 0
include/core/code.h

@@ -45,4 +45,5 @@ AFUN_CORE_EXPORT CodeUInt getCodeEndCount(af_Code *code);
 AFUN_CORE_EXPORT char *getCodeElementData(af_Code *code);
 AFUN_CORE_EXPORT CodeUInt getCodeElementCount(af_Code *code);
 AFUN_CORE_EXPORT char *getCodeMD5(af_Code *code);
+AFUN_CORE_EXPORT bool codeSemanticCheck(af_Code *code);
 #endif //AFUN_BYTECODE

+ 1 - 2
src/core/bytecode.c

@@ -20,7 +20,7 @@ char const * const writeByteCodeError[5] = {
 };
 
 char const * const readByteCodeError[7] = {
-        "File write error.",  // 0
+        "File read error.",  // 0
         NULL,  // 无错误
         "File open error.",  // 2
         "The file is not an aFun Bytecode file.",  // 3
@@ -94,7 +94,6 @@ int readByteCode(af_Code **code, FilePath path) {
 
     if (!readAllCode(code, path, file)) {
         re = 5;
-        freeAllCode(*code);
         goto RETURN_;
     }
 

+ 46 - 1
src/core/code.c

@@ -269,6 +269,9 @@ bool writeAllCode(af_Code *bt, FILE *file) {
     if (bt == NULL || bt->path == NULL)
         return false;
 
+    if (!codeSemanticCheck(bt))
+        goto RETURN_FALSE;
+
     for (NULL; bt != NULL; bt = bt->next) {
         if (!writeCode(bt, file))
             goto RETURN_FALSE;
@@ -334,11 +337,16 @@ bool readAllCode(af_Code **bt, FilePath path, FILE *file) {
             break;
     }
 
-    if (*base != NULL)
+    if (*base != NULL && path != NULL)
         (*base)->path = strCopy(path);
+
+    if (!codeSemanticCheck(*base))
+        goto RETURN_FALSE;
     return true;
 
 RETURN_FALSE:
+    freeAllCode(*bt);
+    *bt = NULL;
     return false;
 }
 
@@ -546,3 +554,40 @@ char *getCodeMD5(af_Code *code) {
         snprintf((char *)md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
     return md5str;
 }
+
+static bool codeElementCheck(const char *data) {
+    return data != NULL;
+}
+
+/*
+ * 函数名: codeSemanticCheck
+ * 目标: 检查code结构体是否符合语义
+ */
+bool codeSemanticCheck(af_Code *code) {
+    CodeUInt layer = 0;
+    if (code == NULL || code->path == NULL)
+        return false;
+
+    for (NULL; code != NULL; code = code->next) {
+        if (code->type != code_block && code->type != code_element)
+            return false;
+        if (code->type == code_element && !codeElementCheck(code->element.data))
+            return false;
+        if (code->type == code_block) {
+            if (code->block.type != parentheses &&
+                code->block.type != brackets && code->block.type != curly)
+                return false;
+            if (!code->block.is_empty && code->code_end != 0)  // 正常情况下, block的code_end为0, 但empty时除外
+                return false;
+        }
+        if (code->prefix != NUL && !strchr(ALL_PREFIX, code->prefix))
+            return false;
+        if (LAYER_ADD1(code))
+            layer++;
+        if (layer - code->code_end < 0)
+            return false;
+        layer -= code->code_end;
+    }
+
+    return true;
+}

+ 3 - 3
src/core/run.c

@@ -121,13 +121,13 @@ static bool iterCodeInit(af_Code *code, int mode, af_Environment *env) {
 
     switch (mode) {
         case 0:
-            if (env->activity->type != act_top || code == NULL || code->path == NULL)
+            if (env->activity->type != act_top || !codeSemanticCheck(code))
                 return false;
             setActivityBtTop(NULL, env->activity);  // 直接就在NORMAL期, bt_top不被设定
             setActivityBtStart(code, env->activity);
             break;
         case 1: {
-            if (env->activity->type != act_top || code == NULL || code->path == NULL)
+            if (env->activity->type != act_top)
                 return false;
             char *name = getFileName(code->path);
             pushImportActivity(code, NULL, name, env);
@@ -136,7 +136,7 @@ static bool iterCodeInit(af_Code *code, int mode, af_Environment *env) {
             break;
         }
         case 2:
-            if (env->activity->type == act_gc || env->activity->bt_next == NULL || code != NULL)
+            if (env->activity->type == act_gc || !codeSemanticCheck(env->activity->bt_start) || env->activity->bt_next == NULL || code != NULL)
                 return false;
             break;
         case 3:

+ 0 - 1
src/runtime/aFunlang.c

@@ -166,7 +166,6 @@ int runCodeFromFileByte(FilePath file, FILE *error_file, af_Environment *env) {
     int res = readByteCode(&code, file);
     if(res != 1) {
         fprintf(error_file, "Load bytecode file error [%s] [Load at %s].\n", readByteCodeError[res], file);
-        freeAllCode(code);
         return -2;
     }