enowars5-service-stldoctor

STL-Analyzing A/D Service for ENOWARS5 in 2021
git clone https://git.sinitax.com/sinitax/enowars5-service-stldoctor
Log | Files | Refs | README | LICENSE | sfeed.txt

commit c7c6f38c144142563e135eceb5daed492c203a85
parent 14bc8a3883663656cd4254567a978002c062992d
Author: Louis Burda <quent.burda@gmail.com>
Date:   Fri, 25 Jun 2021 01:51:22 +0200

fix free() of potentially uninitialized pointer and minor refactors in service

Diffstat:
Mchecker/src/checker.py | 2+-
Mchecker/test.sh | 2+-
Mservice/src/main.c | 41++++++++++++++++++++++-------------------
Mservice/src/stlfile.c | 51++++++++++++++++++++++++---------------------------
Mservice/src/util.h | 6++++--
Msrc/main.c | 41++++++++++++++++++++++-------------------
Msrc/stlfile.c | 51++++++++++++++++++++++++---------------------------
Msrc/util.h | 6++++--
8 files changed, 102 insertions(+), 98 deletions(-)

diff --git a/checker/src/checker.py b/checker/src/checker.py @@ -120,7 +120,7 @@ class STLDoctorChecker(BaseChecker): else: content = b"solid\n" facet_count = rand.randint(4, 30) - indent = bytes([rand.choice(b"\t\n ") for i in range(rand.randint(1, 4))]) + indent = bytes([rand.choice(b"\t ") for i in range(rand.randint(1, 4))]) for fi in range(facet_count): if malformed and randchoice == 0: # malformed by wrong keyword content += indent * 1 + b"facet nornal " diff --git a/checker/test.sh b/checker/test.sh @@ -44,7 +44,7 @@ try() { python3 src/checker.py -j run -v "$variant" -x 4000 \ --flag ENOTESTFLAG123= --flag_regex 'ENO.*=' -i $taskid \ ${@:3} "$cmd" > "$tmpfile" - res="$(cat $tmpfile | grep -a Result: | tail -n1 | grep -a -o OK)" + res="$(cat $tmpfile | grep -a -o 'Result: .*' | tail -n1 | cut -d' ' -f2)" fi if [ "$res" != "OK" ]; then newfile="fails/err-$pid" diff --git a/service/src/main.c b/service/src/main.c @@ -43,7 +43,7 @@ struct command commands[] = { { "auth", auth_cmd, "Login to upload files to a private dir." } }; -struct parseinfo cached; +struct parseinfo cached = { 0 }; char *resultdir; int echo = 0, loggedin = 0; @@ -52,7 +52,7 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) { char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; FILE *f = NULL; - int status = 0; + int status = OK; DIR *d; if (loggedin) @@ -64,12 +64,12 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) modelpath = aprintf("%s/%s", dirpath, "model"); if (!(f = fopen(modelpath, "w+"))) goto fail; if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail; - NFCLOSE(f); + FCLOSE(f); infopath = aprintf("%s/%s", dirpath, "info"); if (!(f = fopen(infopath, "w+"))) goto fail; if (save_info(info, f) != OK) goto fail; - NFCLOSE(f); + FCLOSE(f); exit: if (f) fclose(f); @@ -85,7 +85,7 @@ fail: if (modelpath) remove(modelpath); if (dirpath) remove(dirpath); - status = 1; + status = FAIL; goto exit; } @@ -99,9 +99,9 @@ access_authorized(const char *file) int handle_download(const char *scandir) { - char *infopath, *modelpath; + char *infopath = NULL, *modelpath = NULL; size_t i, size; - int status = 0; + int status = OK; FILE *f; infopath = aprintf("%s/%s", scandir, "info"); @@ -109,12 +109,13 @@ handle_download(const char *scandir) ERR("Selected result is missing!\n"); goto fail; } + free_info(&cached); if (load_info(&cached, f) != OK) { ERR("Failed to parse info file!\n"); goto fail; } - NFCLOSE(f); + FCLOSE(f); print_info(&cached); @@ -134,7 +135,7 @@ handle_download(const char *scandir) printf("Here you go.. (%liB)\n", size); while ((i = getc(f)) != EOF) putc(i, stdout); - NFCLOSE(f); + FCLOSE(f); } exit: @@ -144,7 +145,7 @@ exit: return status; fail: - status = 1; + status = FAIL; goto exit; } @@ -276,12 +277,12 @@ search_cmd(const char *arg) } scandir = aprintf("%s/%s", resultdir, paths[which]); - if (handle_download(scandir)) goto cleanup; - NFREE(scandir); + if (handle_download(scandir) != OK) goto cleanup; + FREE(scandir); } cleanup: - free(scandir); + FREE(scandir); for (i = 0; i < pathc; i++) free(paths[i]); free(paths); @@ -309,13 +310,16 @@ list_cmd(const char *arg) path = aprintf("%s/%s/info", resultdir, de->d_name); if ((f = fopen(path, "r")) && load_info(&info, f) == OK) { print_info(&info); + free_info(&info); } else { - ERR("Failed to read saved file info!\n"); + ERR("Failed to read file info!\n"); } if (f) fclose(f); free(path); } } + + closedir(d); } void @@ -345,7 +349,7 @@ auth_cmd(const char *arg) free(resultdir); resultdir = ndir; loggedin = 1; - cached.valid = 0; + free_info(&cached); } void @@ -359,7 +363,6 @@ cleanexit() int main() { - struct command *c; const char *cmd, *envstr; char *cp, *arg; int exit, i, cmdlen; @@ -389,9 +392,9 @@ main() cmdlen = cp ? cp - cmd : strlen(cmd); for (i = 0; i < ARRSIZE(commands); i++) { - c = &commands[i]; - if (!strncmp(c->name, cmd, cmdlen) && !c->name[cmdlen]) { - c->func(arg); + if (!strncmp(commands[i].name, cmd, cmdlen) + && !commands[i].name[cmdlen]) { + commands[i].func(arg); break; } } diff --git a/service/src/stlfile.c b/service/src/stlfile.c @@ -134,7 +134,7 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) stack_push(&states, STATE_SOLID); if (stack_ind(&states, KW_SOLID_BEGIN) != -1) { FMT_ERR("Multiple nested solids!\n"); - goto format_error; + goto fail; } tmp = bp; if (!consume_keyword(&bp) @@ -148,14 +148,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) if ((kw = stack_pop(&states)) != STATE_SOLID) { FMT_ERR("Improper nesting, parent: %s\n", kwmap[kw].str); - goto format_error; + goto fail; } tmp = bp; if (info->solidname && !consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { if (strncmp(info->solidname, arg, end - arg)) { FMT_ERR("Solid names do not match!\n"); - goto format_error; + goto fail; } } else { bp = tmp; @@ -165,14 +165,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) stack_push(&states, STATE_LOOP); if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { FMT_ERR("Multiple nested loops!\n"); - goto format_error; + goto fail; } break; case KW_LOOP_END: if ((kw = stack_pop(&states)) != STATE_LOOP) { FMT_ERR("Improper nesting, parent: %s\n", kwmap[kw].str); - goto format_error; + goto fail; } info->loopcount++; break; @@ -180,17 +180,17 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) stack_push(&states, STATE_FACET); if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { FMT_ERR("Multiple nested facets!\n"); - goto format_error; + goto fail; } for (i = 0; i < 3; i++) { if (!(arg = consume_arg(&bp, &end))) { FMT_ERR("Facet with < 3 args!\n"); - goto format_error; + goto fail; } farg = strtof(arg, &tmp); if (!isws(*tmp)) { FMT_ERR("Facet arg '%s'\n", arg); - goto format_error; + goto fail; } } break; @@ -198,19 +198,19 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) if ((kw = stack_pop(&states)) != STATE_FACET) { FMT_ERR("Improper nesting, parent: %s\n", kwmap[kw].str); - goto format_error; + goto fail; } break; case KW_VERTEX: for (i = 0; i < 3; i++) { if (!(arg = consume_arg(&bp, &end))) { FMT_ERR("Vertex with < 3 args\n"); - goto format_error; + goto fail; } farg = strtof(arg, &tmp); if (!isws(*tmp)) { FMT_ERR("Vertex arg '%s'\n", arg); - goto format_error; + goto fail; } info->bbmin[i] = MIN(info->bbmin[i], farg); info->bbmax[i] = MAX(info->bbmax[i], farg); @@ -219,26 +219,26 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) case KW_UNKNOWN: prev = skipws(prev); FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, prev); - goto format_error; + goto fail; } prev = bp; } if (states.count) { FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, bp); - goto format_error; + goto fail; } bp = skipws(bp); if (*bp) { FMT_ERR("Extraneous data at end of file\n"); - goto format_error; + goto fail; } stack_free(&states); return OK; -format_error: +fail: stack_free(&states); return FAIL; } @@ -305,7 +305,7 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) return OK; fail: - NFREE(info->solidname); + FREE(info->solidname); return FAIL; } @@ -316,7 +316,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len) const char *resp; char *bp; - free_info(info); + if (info->valid) + free_info(info); if (len < 10) { ERR("File too small!\n"); @@ -331,8 +332,6 @@ parse_file(struct parseinfo *info, char *buf, size_t len) : parse_file_bin(info, buf, len); if (status == FAIL) return FAIL; - if (!info->solidname) info->solidname = checkp(strdup("")); - if (!info->modelname) { resp = ask("Please enter your model name: "); if (strlen(resp) < 4) { @@ -342,6 +341,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len) info->modelname = checkp(strdup(resp)); } + if (!info->solidname) info->solidname = checkp(strdup("")); + info->hash = checkp(strdup(mhash(info->modelname, -1))); return OK; @@ -406,12 +407,9 @@ print_info(struct parseinfo *info) { int i, k; -#define FILTERCHAR(c) ((c) >= 32 ? (c) : ' ') - printf(" === Model info === \n"); printf(" File Size: %u\n", info->filesize); - if (info->type == TYPE_BIN) { printf(" Header:\n"); for (i = 0; i < 80; i += k) { @@ -420,11 +418,10 @@ print_info(struct parseinfo *info) printf(" %02x", (uint8_t) info->header[i+k]); printf(" | "); for (k = 0; k < MIN(80 - i, 20); k++) - printf("%c", FILTERCHAR(info->header[i+k])); + putchar(PRINTABLE(info->header[i+k])); printf("\n"); } } - printf(" Model ID: %s\n", info->hash); printf(" Model Name: %s\n", info->modelname); printf(" Solid Name: %s\n", info->solidname); @@ -442,9 +439,9 @@ print_info(struct parseinfo *info) void free_info(struct parseinfo *info) { - NFREE(info->hash); - NFREE(info->modelname); - NFREE(info->solidname); + FREE(info->hash); + FREE(info->modelname); + FREE(info->solidname); info->valid = 0; } diff --git a/service/src/util.h b/service/src/util.h @@ -11,10 +11,12 @@ #define MIN(x,y) ((x) > (y) ? (y) : (x)) #define MAX(x,y) ((x) < (y) ? (y) : (x)) +#define PRINTABLE(c) ((c) >= 32 ? (c) : ' ') + #define ERR(...) printf("ERR: " __VA_ARGS__) -#define NFREE(p) do { free(p); p = NULL; } while (0) -#define NFCLOSE(f) do { fclose(f); f = NULL; } while (0) +#define FREE(p) do { free(p); p = NULL; } while (0) +#define FCLOSE(f) do { if (f) fclose(f); f = NULL; } while (0) #define MHASHLEN 40 diff --git a/src/main.c b/src/main.c @@ -43,7 +43,7 @@ struct command commands[] = { { "auth", auth_cmd, "Login to upload files to a private dir." } }; -struct parseinfo cached; +struct parseinfo cached = { 0 }; char *resultdir; int echo = 0, loggedin = 0; @@ -52,7 +52,7 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) { char *dirpath = NULL, *infopath = NULL, *modelpath = NULL; FILE *f = NULL; - int status = 0; + int status = OK; DIR *d; if (loggedin) @@ -64,12 +64,12 @@ save_submission(struct parseinfo *info, char *stldata, int stlsize) modelpath = aprintf("%s/%s", dirpath, "model"); if (!(f = fopen(modelpath, "w+"))) goto fail; if (fwrite(stldata, 1, stlsize, f) != stlsize) goto fail; - NFCLOSE(f); + FCLOSE(f); infopath = aprintf("%s/%s", dirpath, "info"); if (!(f = fopen(infopath, "w+"))) goto fail; if (save_info(info, f) != OK) goto fail; - NFCLOSE(f); + FCLOSE(f); exit: if (f) fclose(f); @@ -85,7 +85,7 @@ fail: if (modelpath) remove(modelpath); if (dirpath) remove(dirpath); - status = 1; + status = FAIL; goto exit; } @@ -99,9 +99,9 @@ access_authorized(const char *file) int handle_download(const char *scandir) { - char *infopath, *modelpath; + char *infopath = NULL, *modelpath = NULL; size_t i, size; - int status = 0; + int status = OK; FILE *f; infopath = aprintf("%s/%s", scandir, "info"); @@ -109,12 +109,13 @@ handle_download(const char *scandir) ERR("Selected result is missing!\n"); goto fail; } + free_info(&cached); if (load_info(&cached, f) != OK) { ERR("Failed to parse info file!\n"); goto fail; } - NFCLOSE(f); + FCLOSE(f); print_info(&cached); @@ -134,7 +135,7 @@ handle_download(const char *scandir) printf("Here you go.. (%liB)\n", size); while ((i = getc(f)) != EOF) putc(i, stdout); - NFCLOSE(f); + FCLOSE(f); } exit: @@ -144,7 +145,7 @@ exit: return status; fail: - status = 1; + status = FAIL; goto exit; } @@ -276,12 +277,12 @@ search_cmd(const char *arg) } scandir = aprintf("%s/%s", resultdir, paths[which]); - if (handle_download(scandir)) goto cleanup; - NFREE(scandir); + if (handle_download(scandir) != OK) goto cleanup; + FREE(scandir); } cleanup: - free(scandir); + FREE(scandir); for (i = 0; i < pathc; i++) free(paths[i]); free(paths); @@ -309,13 +310,16 @@ list_cmd(const char *arg) path = aprintf("%s/%s/info", resultdir, de->d_name); if ((f = fopen(path, "r")) && load_info(&info, f) == OK) { print_info(&info); + free_info(&info); } else { - ERR("Failed to read saved file info!\n"); + ERR("Failed to read file info!\n"); } if (f) fclose(f); free(path); } } + + closedir(d); } void @@ -345,7 +349,7 @@ auth_cmd(const char *arg) free(resultdir); resultdir = ndir; loggedin = 1; - cached.valid = 0; + free_info(&cached); } void @@ -359,7 +363,6 @@ cleanexit() int main() { - struct command *c; const char *cmd, *envstr; char *cp, *arg; int exit, i, cmdlen; @@ -389,9 +392,9 @@ main() cmdlen = cp ? cp - cmd : strlen(cmd); for (i = 0; i < ARRSIZE(commands); i++) { - c = &commands[i]; - if (!strncmp(c->name, cmd, cmdlen) && !c->name[cmdlen]) { - c->func(arg); + if (!strncmp(commands[i].name, cmd, cmdlen) + && !commands[i].name[cmdlen]) { + commands[i].func(arg); break; } } diff --git a/src/stlfile.c b/src/stlfile.c @@ -134,7 +134,7 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) stack_push(&states, STATE_SOLID); if (stack_ind(&states, KW_SOLID_BEGIN) != -1) { FMT_ERR("Multiple nested solids!\n"); - goto format_error; + goto fail; } tmp = bp; if (!consume_keyword(&bp) @@ -148,14 +148,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) if ((kw = stack_pop(&states)) != STATE_SOLID) { FMT_ERR("Improper nesting, parent: %s\n", kwmap[kw].str); - goto format_error; + goto fail; } tmp = bp; if (info->solidname && !consume_keyword(&bp) && (arg = consume_arg(&bp, &end))) { if (strncmp(info->solidname, arg, end - arg)) { FMT_ERR("Solid names do not match!\n"); - goto format_error; + goto fail; } } else { bp = tmp; @@ -165,14 +165,14 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) stack_push(&states, STATE_LOOP); if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { FMT_ERR("Multiple nested loops!\n"); - goto format_error; + goto fail; } break; case KW_LOOP_END: if ((kw = stack_pop(&states)) != STATE_LOOP) { FMT_ERR("Improper nesting, parent: %s\n", kwmap[kw].str); - goto format_error; + goto fail; } info->loopcount++; break; @@ -180,17 +180,17 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) stack_push(&states, STATE_FACET); if (stack_ind(&states, KW_LOOP_BEGIN) != -1) { FMT_ERR("Multiple nested facets!\n"); - goto format_error; + goto fail; } for (i = 0; i < 3; i++) { if (!(arg = consume_arg(&bp, &end))) { FMT_ERR("Facet with < 3 args!\n"); - goto format_error; + goto fail; } farg = strtof(arg, &tmp); if (!isws(*tmp)) { FMT_ERR("Facet arg '%s'\n", arg); - goto format_error; + goto fail; } } break; @@ -198,19 +198,19 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) if ((kw = stack_pop(&states)) != STATE_FACET) { FMT_ERR("Improper nesting, parent: %s\n", kwmap[kw].str); - goto format_error; + goto fail; } break; case KW_VERTEX: for (i = 0; i < 3; i++) { if (!(arg = consume_arg(&bp, &end))) { FMT_ERR("Vertex with < 3 args\n"); - goto format_error; + goto fail; } farg = strtof(arg, &tmp); if (!isws(*tmp)) { FMT_ERR("Vertex arg '%s'\n", arg); - goto format_error; + goto fail; } info->bbmin[i] = MIN(info->bbmin[i], farg); info->bbmax[i] = MAX(info->bbmax[i], farg); @@ -219,26 +219,26 @@ parse_file_ascii(struct parseinfo *info, char *buf, size_t len) case KW_UNKNOWN: prev = skipws(prev); FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, prev); - goto format_error; + goto fail; } prev = bp; } if (states.count) { FMT_ERR("Expected keyword, got:\n%.*s...\n", 30, bp); - goto format_error; + goto fail; } bp = skipws(bp); if (*bp) { FMT_ERR("Extraneous data at end of file\n"); - goto format_error; + goto fail; } stack_free(&states); return OK; -format_error: +fail: stack_free(&states); return FAIL; } @@ -305,7 +305,7 @@ parse_file_bin(struct parseinfo *info, char *buf, size_t len) return OK; fail: - NFREE(info->solidname); + FREE(info->solidname); return FAIL; } @@ -316,7 +316,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len) const char *resp; char *bp; - free_info(info); + if (info->valid) + free_info(info); if (len < 10) { ERR("File too small!\n"); @@ -332,8 +333,6 @@ parse_file(struct parseinfo *info, char *buf, size_t len) : parse_file_bin(info, buf, len); if (status == FAIL) return FAIL; - if (!info->solidname) info->solidname = checkp(strdup("")); - if (!info->modelname) { resp = ask("Please enter your model name: "); if (strlen(resp) < 4) { @@ -343,6 +342,8 @@ parse_file(struct parseinfo *info, char *buf, size_t len) info->modelname = checkp(strdup(resp)); } + if (!info->solidname) info->solidname = checkp(strdup("")); + info->hash = checkp(strdup(mhash(info->modelname, -1))); return OK; @@ -407,12 +408,9 @@ print_info(struct parseinfo *info) { int i, k; -#define FILTERCHAR(c) ((c) >= 32 ? (c) : ' ') - printf(" === Model info === \n"); printf(" File Size: %u\n", info->filesize); - if (info->type == TYPE_BIN) { printf(" Header:\n"); for (i = 0; i < 80; i += k) { @@ -421,11 +419,10 @@ print_info(struct parseinfo *info) printf(" %02x", (uint8_t) info->header[i+k]); printf(" | "); for (k = 0; k < MIN(80 - i, 20); k++) - printf("%c", FILTERCHAR(info->header[i+k])); + putchar(PRINTABLE(info->header[i+k])); printf("\n"); } } - printf(" Model ID: %s\n", info->hash); printf(" Model Name: %s\n", info->modelname); printf(" Solid Name: %s\n", info->solidname); @@ -443,9 +440,9 @@ print_info(struct parseinfo *info) void free_info(struct parseinfo *info) { - NFREE(info->hash); - NFREE(info->modelname); - NFREE(info->solidname); + FREE(info->hash); + FREE(info->modelname); + FREE(info->solidname); info->valid = 0; } diff --git a/src/util.h b/src/util.h @@ -11,10 +11,12 @@ #define MIN(x,y) ((x) > (y) ? (y) : (x)) #define MAX(x,y) ((x) < (y) ? (y) : (x)) +#define PRINTABLE(c) ((c) >= 32 ? (c) : ' ') + #define ERR(...) fprintf(stderr, "ERR: " __VA_ARGS__) -#define NFREE(p) do { free(p); p = NULL; } while (0) -#define NFCLOSE(f) do { fclose(f); f = NULL; } while (0) +#define FREE(p) do { free(p); p = NULL; } while (0) +#define FCLOSE(f) do { if (f) fclose(f); f = NULL; } while (0) #define MHASHLEN 40