ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

Select the types of activity you want to include in your feed.

tobi / test / t_corpus.c
4.3 kB 150 lines
1#include "t.h" 2 3#include "cf.h" 4#include "da.h" 5#include "dc.h" 6#include "js.h" 7#include "p.h" 8 9#include <dirent.h> 10#include <errno.h> 11#include <sys/stat.h> 12 13#ifndef TOBI_SRC_DIR 14#define TOBI_SRC_DIR "." 15#endif 16 17static int read_blob(const char *path, uint8_t **data, size_t *len) { 18 FILE *fp = fopen(path, "rb"); 19 if (!fp) { 20 fprintf(stderr, "open %s: %s\n", path, strerror(errno)); 21 return 0; 22 } 23 if (fseek(fp, 0, SEEK_END) != 0) { 24 fclose(fp); 25 return 0; 26 } 27 long n = ftell(fp); 28 if (n < 0) { 29 fclose(fp); 30 return 0; 31 } 32 rewind(fp); 33 *len = (size_t)n; 34 *data = malloc(*len ? *len : 1u); 35 if (!*data) { 36 fclose(fp); 37 return 0; 38 } 39 if (*len && fread(*data, 1, *len, fp) != *len) { 40 free(*data); 41 fclose(fp); 42 return 0; 43 } 44 fclose(fp); 45 return 1; 46} 47 48static int stable_emit_blob(const char *label, const uint8_t *data, size_t len, int strict_should_pass) { 49 int ok = 0; 50 tobi_parse_result a; 51 tobi_parse_result b; 52 tobi_parse_result strict; 53 (void)tobi_parse(data, len, 0, &a); 54 (void)tobi_parse(data, len, 0, &b); 55 int strict_ok = tobi_parse(data, len, 1, &strict); 56 int expected_strict_ok = strict_should_pass && a.diag.len == 0; 57 (void)tobi_cf_recover(a.root, &a.diag); 58 (void)tobi_cf_recover(b.root, &b.diag); 59 char *aj = tobi_js_emit(&a); 60 char *bj = tobi_js_emit(&b); 61 char *ad = tobi_dc_emit(a.root, &a.diag); 62 char *bd = tobi_dc_emit(b.root, &b.diag); 63 char *aa = tobi_da_emit(data, len, &a.meta); 64 char *ba = tobi_da_emit(data, len, &b.meta); 65 ok = aj != NULL && bj != NULL && ad != NULL && bd != NULL && aa != NULL && ba != NULL && 66 strcmp(aj, bj) == 0 && aj[0] == '{' && strstr(aj, "\"meta\"") != NULL && 67 strstr(aj, "\"ir\"") != NULL && strstr(aj, ",}") == NULL && strstr(aj, ",]") == NULL && 68 ad[0] != '\0' && aa[0] != '\0' && strcmp(ad, bd) == 0 && strcmp(aa, ba) == 0; 69 if (expected_strict_ok) { 70 ok = ok && strict_ok && !tobi_diag_has_error(&strict.diag); 71 } else { 72 ok = ok && (!strict_ok || tobi_diag_has_error(&strict.diag)); 73 } 74 if (!ok) { 75 fprintf(stderr, "corpus regression failed for %s\n", label); 76 } 77 free(aa); 78 free(ba); 79 free(ad); 80 free(bd); 81 free(aj); 82 free(bj); 83 tobi_parse_result_free(&a); 84 tobi_parse_result_free(&b); 85 tobi_parse_result_free(&strict); 86 return ok ? 0 : 1; 87} 88 89static int stable_emit(const char *path, int strict_should_pass) { 90 uint8_t *data = NULL; 91 size_t len = 0; 92 int rc = 1; 93 if (!read_blob(path, &data, &len)) { 94 return 1; 95 } 96 rc = stable_emit_blob(path, data, len, strict_should_pass); 97 if (rc == 0 && len > 1) { 98 size_t cuts[] = {1u, len / 2u, len - 1u}; 99 for (size_t i = 0; i < sizeof(cuts) / sizeof(cuts[0]); i++) { 100 if (cuts[i] == 0 || cuts[i] >= len) { 101 continue; 102 } 103 char label[900]; 104 snprintf(label, sizeof(label), "%s truncated:%zu", path, cuts[i]); 105 if (stable_emit_blob(label, data, cuts[i], 0) != 0) { 106 rc = 1; 107 break; 108 } 109 } 110 } 111 free(data); 112 return rc; 113} 114 115static int walk_dir(const char *rel, size_t *count, size_t *bad_count) { 116 char dir_path[512]; 117 snprintf(dir_path, sizeof(dir_path), "%s/%s", TOBI_SRC_DIR, rel); 118 DIR *dir = opendir(dir_path); 119 T_CHECK(dir != NULL); 120 struct dirent *de = NULL; 121 while ((de = readdir(dir)) != NULL) { 122 if (de->d_name[0] == '.') { 123 continue; 124 } 125 char path[768]; 126 snprintf(path, sizeof(path), "%s/%s", dir_path, de->d_name); 127 struct stat st; 128 T_CHECK(stat(path, &st) == 0); 129 if (S_ISREG(st.st_mode)) { 130 int bad = strstr(de->d_name, "bad") != NULL; 131 T_CHECK(stable_emit(path, !bad) == 0); 132 (*count)++; 133 if (bad) { 134 (*bad_count)++; 135 } 136 } 137 } 138 T_CHECK(closedir(dir) == 0); 139 return 0; 140} 141 142int t_corpus(void) { 143 size_t count = 0; 144 size_t bad_count = 0; 145 T_CHECK(walk_dir("sam", &count, &bad_count) == 0); 146 T_CHECK(walk_dir("fuzz/seed", &count, &bad_count) == 0); 147 T_CHECK(count >= 9); 148 T_CHECK(bad_count >= 2); 149 return 0; 150}