poe

Уређивач .po фајлова
git clone https://git.sr.ht/~strahinja/poe
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување e5eccfd2bdd28eddc4f8895e530fe7c284ebcfa3
родитељ 7fd3f47cad89c7dbc872fbae5b53ea385cb1e897
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Fri, 17 May 2024 00:13:11 +0200

Fix a few potential bugs thanks to LLVM's scan-build

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
Mdraw.c | 3++-
Mpo.c | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mpoe.c | 59++++++++++++++++++++++++++++++++++++++++-------------------
измењених датотека: 3, додавања: 135(+), брисања: 52(-)

diff --git a/draw.c b/draw.c @@ -90,7 +90,7 @@ init_drawstate(struct DrawState* state, char* error, char* filename, { state->error = error; state->filename = filename; - state->real_filename = filename; + state->real_filename = NULL; state->backup_filename = NULL; state->rfn_len = 0; state->search = NULL; @@ -208,6 +208,7 @@ set_nplurals(struct DrawState* state, struct PoEntry* entry) else if (read_number && *ppf >= '0' && *ppf <= '9') { *ptoken++ = *ppf++; + *ptoken = 0; } else if (read_number && *ppf == ';') { diff --git a/po.c b/po.c @@ -280,7 +280,12 @@ u32_set_msgstr(struct PoEntry* entry, const uint32_t* msgstr, int msgstr_index, entry->msgstr_count * sizeof(size_t)); } if (!newmsgstr || !newmsgstr_size || !newmsgstr_len) + { + free(newmsgstr); + free(newmsgstr_len); + free(newmsgstr_size); return NULL; + } *(newmsgstr + msgstr_index) = NULL; entry->msgstr = newmsgstr; entry->msgstr_size = newmsgstr_size; @@ -478,12 +483,15 @@ load_file(struct DrawState* dstate, long* lineno, long* col) /* when the .po file is not a standard text file (no LF at end) */ if (dstate->msgid_count > 1) { - if (entry->msgid) - /* regular entry */ - dstate->msgid_count++; - else if (entry->comment_lines > 0) - /* obsolete entry */ - entry->obsolete = 1; + if (entry) + { + if (entry->msgid) + /* regular entry */ + dstate->msgid_count++; + else if (entry->comment_lines > 0) + /* obsolete entry */ + entry->obsolete = 1; + } #ifndef PLURAL_STRING if (has_plural_msgid && !dstate->entries->plural_forms) STRLCPY(errors[ERR_NO_PLURAL_FORMS], dstate->error, @@ -527,6 +535,7 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, char* backup_filename = NULL; #endif struct stat st; + int result = SAVE_ERR_NONE; char* real_filename = NULL; size_t rfn_len = 0; Flags flags; @@ -535,7 +544,10 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, return SAVE_ERR_CANT_ALLOC; #ifdef CREATE_BACKUPS if (!(backup_filename = calloc(MAXPATH, 1))) + { + free(real_filename); return SAVE_ERR_CANT_ALLOC; + } #endif #ifdef CREATE_BACKUPS @@ -545,31 +557,52 @@ save_file(const struct PoEntry* entries, const size_t real_msgid_count, { rfn_len = readlink(filename, real_filename, MAXPATH); if (rfn_len == -1) - return SAVE_ERR_CANT_READLINK; + { + result = SAVE_ERR_CANT_READLINK; + goto save_loop_entries_done; + } real_filename[rfn_len] = 0; if (stat(real_filename, &st) == -1) - return SAVE_ERR_CANT_STAT_FILE; + { + result = SAVE_ERR_CANT_STAT_FILE; + goto save_loop_entries_done; + } } STRLCPY(filename, backup_filename, MAXPATH); STRLCAT(backup_suffix, backup_filename, MAXPATH); if (rename(rfn_len > 0 ? real_filename : filename, backup_filename) == -1) - return SAVE_ERR_CANT_MOVE_FILE; + { + result = SAVE_ERR_CANT_MOVE_FILE; + goto save_loop_entries_done; + } } else - return SAVE_ERR_CANT_STAT_FILE; + { + result = SAVE_ERR_CANT_STAT_FILE; + goto save_loop_entries_done; + } #endif if (!(output = fopen(rfn_len > 0 ? real_filename : filename, "wt"))) - return SAVE_ERR_CANT_OPEN_FILE; + { + result = SAVE_ERR_CANT_OPEN_FILE; + goto save_loop_entries_done; + } #ifdef CREATE_BACKUPS if (rfn_len > 0) { if (unlink(filename) == -1) - return SAVE_ERR_CANT_UNLINK; + { + result = SAVE_ERR_CANT_UNLINK; + goto save_loop_entries_done; + } if (symlink(real_filename, filename) == -1) - return SAVE_ERR_CANT_SYMLINK; + { + result = SAVE_ERR_CANT_SYMLINK; + goto save_loop_entries_done; + } } chmod(rfn_len > 0 ? real_filename : filename, st.st_mode); #endif @@ -597,7 +630,10 @@ save_comments: else u8_comment = realloc(u8_comment, size); if (!u8_comment) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } unicode_string_to_u8(u8_comment, size, *(current->comments + c), len); fprintf(output, "#%s%s\n", current->obsolete ? "~" : "", @@ -623,7 +659,10 @@ save_comments: u8_trans_comment = realloc(u8_trans_comment, size); if (!u8_trans_comment) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } unicode_string_to_u8(u8_trans_comment, size, *(current->trans_comments + tc), len); fprintf(output, "#.%s%s\n", @@ -711,7 +750,10 @@ save_obsolete_check: u8_msgid = malloc(size); if (!u8_msgid) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } memset(u8_msgid, 0, size); @@ -729,7 +771,10 @@ save_obsolete_check: size = current->msgid_size * UTF8REPMAX + 1; u8_msgid = malloc(size); if (!u8_msgid) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } memset(u8_msgid, 0, size); @@ -770,7 +815,10 @@ save_obsolete_check: size = len * UTF8REPMAX + 1; u8_msgid = malloc(size); if (!u8_msgid) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } memset(u8_msgid, 0, size); @@ -789,7 +837,10 @@ save_obsolete_check: size = current->msgid_plural_size * UTF8REPMAX + 1; u8_msgid = malloc(size); if (!u8_msgid) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } memset(u8_msgid, 9, size); @@ -844,7 +895,10 @@ save_obsolete_check: size = len * UTF8REPMAX + 1; u8_msgstr = malloc(size); if (!u8_msgstr) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } memset(u8_msgstr, 0, size); @@ -937,7 +991,10 @@ save_obsolete_check: size = len * UTF8REPMAX + 1; u8_msgstr = malloc(size); if (!u8_msgstr) - return SAVE_ERR_CANT_ALLOC; + { + result = SAVE_ERR_CANT_ALLOC; + goto save_loop_entries_done; + } memset(u8_msgstr, 0, size); @@ -980,7 +1037,7 @@ save_loop_entries_done: #endif free(real_filename); - return SAVE_ERR_NONE; + return result; } int @@ -1171,6 +1228,7 @@ parse_po_line(const char* line, struct DrawState* dstate, (*col)++; } } + *ptoken = 0; if (*pstate == PS_NONE) { struct PoEntry* newchunk = NULL; @@ -1195,8 +1253,6 @@ parse_po_line(const char* line, struct DrawState* dstate, } if (*token) { - *ptoken = 0; - if (*pstate & PS_MSGID) set_msgid(*current_entry, token, 1); else if (*pstate & PS_MSGID_PLURAL) @@ -1204,8 +1260,9 @@ parse_po_line(const char* line, struct DrawState* dstate, set_msgid_plural(*current_entry, token, 1); if (*current_entry != dstate->entries) for (int i = 0; i < dstate->nplurals; i++) - set_msgstr(*current_entry, NULL, i, 0, - dstate); + if (!set_msgstr(*current_entry, NULL, i, + 0, dstate)) + return PARSE_ERR_ALLOC; } else if (*pstate & PS_MSGSTR) { @@ -1221,11 +1278,15 @@ parse_po_line(const char* line, struct DrawState* dstate, } } - set_msgstr(*current_entry, token, 0, 1, dstate); + if (!set_msgstr(*current_entry, token, 0, 1, dstate)) + return PARSE_ERR_ALLOC; } else if (*pstate & PS_MSGSTR_ARRAY) - set_msgstr(*current_entry, token, *msgstr_index, 1, - dstate); + { + if (!set_msgstr(*current_entry, token, *msgstr_index, 1, + dstate)) + return PARSE_ERR_ALLOC; + } else if (*pstate & PS_COMMENT_TRAN) { uint32_t* u32_token = NULL; @@ -1277,7 +1338,7 @@ parse_po_line(const char* line, struct DrawState* dstate, dstate->fuzzy_count++; ptoken += strlen(flag_strings[FL_FUZZY]); } - else if (starts_with(ptoken, ", ")) + else if (*ptoken == ',' && *(ptoken + 1) == ' ') ptoken += 2; else { @@ -1302,8 +1363,8 @@ parse_po_line(const char* line, struct DrawState* dstate, if (!u32_token) return PARSE_ERR_ALLOC; u8_string_to_unicode(u32_token, token, len); - u32_add_comment(*current_entry, u32_token); - (*current_entry)->obsolete = 1; + if (u32_add_comment(*current_entry, u32_token)) + (*current_entry)->obsolete = 1; free(u32_token); } *token = 0; diff --git a/poe.c b/poe.c @@ -2204,16 +2204,16 @@ main(int argc, char** argv) print_error(EINVAL, "No filename given"); } + init_drawstate(&state, error, filename, prompt); + if (stat(filename, &st) == -1 || access(filename, R_OK | W_OK) == -1) - { - perror(PROGRAMNAME); - return errno; - } + goto file_error; if (!S_ISREG(st.st_mode)) - return print_error(EINVAL, "Is not a regular file"); - - init_drawstate(&state, error, filename, prompt); + { + result = print_error(EINVAL, "Is not a regular file"); + goto general_error; + } #ifdef __OpenBSD__ if (unveil(state.filename, "rwc") < 0) @@ -2243,7 +2243,7 @@ main(int argc, char** argv) state.rfn_len = readlink(state.filename, state.real_filename, MAXPATH); if (state.rfn_len == -1) - return print_error(1, strerror(errno)); + goto file_error; state.real_filename[state.rfn_len] = 0; #ifdef __OpenBSD__ if (unveil(state.real_filename, "rwc") < 0) @@ -2253,11 +2253,14 @@ main(int argc, char** argv) } #endif if (stat(state.real_filename, &st) == -1) - return print_error(1, strerror(errno)); + goto file_error; } if (!(state.backup_filename = calloc(MAXPATH, 1))) + { + free(state.real_filename); return print_error(1, "Allocation failed (out of memory?)"); + } /* Backup filename is the target file + suffix if the file to * write is a symlink, otherwise file + suffix */ @@ -2273,7 +2276,7 @@ main(int argc, char** argv) #endif } else - return print_error(1, strerror(errno)); + goto file_error; #endif /* CREATE_BACKUPS */ if (state.rfn_len > 0) @@ -2306,7 +2309,10 @@ main(int argc, char** argv) } if (!S_ISREG(st.st_mode)) - return print_error(EINVAL, "Is not a regular file"); + { + result = print_error(EINVAL, "Is not a regular file"); + goto general_error; + } #ifdef __OpenBSD__ if (unveil(NULL, NULL) < 0) @@ -2330,30 +2336,45 @@ main(int argc, char** argv) { case LOAD_ERR_CANT_ALLOC: case LOAD_ERR_P_ALLOC: - return print_error(result, "Allocation failed (out of memory?)"); + (void)print_error(result, "Allocation failed (out of memory?)"); + goto general_error; case LOAD_ERR_CANT_OPEN_FILE: - return print_error(result, "Cannot open file `%s'", filename); + (void)print_error(result, "Cannot open file `%s'", filename); + goto general_error; case LOAD_ERR_NOT_PO_FILE: - return print_error(result, "Not a .po file `%s'", filename); + (void)print_error(result, "Not a .po file `%s'", filename); + goto general_error; case LOAD_ERR_P_INVAL: - return print_error(result, "Invalid value"); + (void)print_error(result, "Invalid value"); + goto general_error; case LOAD_ERR_P_SYNTAX: - return print_error(result, "%s:%ld:%ld: Syntax error", filename, + (void)print_error(result, "%s:%ld:%ld: Syntax error", filename, lineno, col); + goto general_error; case LOAD_ERR_NONE: if (*error) - return print_error(1, error); + { + result = print_error(1, error); + goto general_error; + } break; default: - return print_error(1, "Unknown error (%d)", result); + result = print_error(1, "Unknown error (%d)", result); + goto general_error; } state.msgid_number = state.msgid_count > 0 ? 1 : 0; state.first_shown_msgid = state.msgid_number; goto init_termbox; file_error: + result = errno; perror(PROGRAMNAME); - return errno; + /* FALLTHROUGH */ + +general_error: + free(state.real_filename); + free(state.backup_filename); + return result; init_termbox: tb_init();