From ba24ef69153a54ae21dfce8c0f89505110d8cec9 Mon Sep 17 00:00:00 2001 From: David Declerck Date: Wed, 17 Jul 2024 14:17:55 +0200 Subject: [PATCH] Merge SVN 4747 --- cobc/ChangeLog | 9 +++ cobc/cobc.c | 109 ++++++++++++++++++-------------- cobc/codegen.c | 8 ++- cobc/flag.def | 2 +- cobc/parser.y | 2 +- cobc/pplex.l | 9 ++- cobc/typeck.c | 5 +- libcob/ChangeLog | 13 ++++ libcob/fbdb.c | 7 +- libcob/fextfh.c | 2 +- libcob/fileio.c | 40 +++++++++--- libcob/fsqlxfd.c | 2 +- libcob/intrinsic.c | 2 +- libcob/mlio.c | 27 ++++++-- tests/testsuite.src/run_misc.at | 20 +++--- 15 files changed, 170 insertions(+), 87 deletions(-) diff --git a/cobc/ChangeLog b/cobc/ChangeLog index 71d6306fc..8c485ea91 100644 --- a/cobc/ChangeLog +++ b/cobc/ChangeLog @@ -159,6 +159,15 @@ with a default of SIGABRT and a configurable coredump via COBC_CORE_ON_ERROR overriding COB_CORE_ON_ERROR (currently fixed "2") +2022-10-08 Simon Sobisch + + * pplex.l (plex_call_destroy): fixed minor memory leak + * cobc.c (compile_level): using enum values instead of numeric constants + * parser.y (examine_format_variant): internally use "MOVE ZERO TO TALLY" + instead of "INITIALIZE TALLY" + * cobc.c: minor reformatting + * flag.def: fixed minor doc issues + 2022-10-06 Simon Sobisch * parser.y (symbolic_characters_clause, class_name_clause): improved diff --git a/cobc/cobc.c b/cobc/cobc.c index d1b09ea4a..21bd254b3 100644 --- a/cobc/cobc.c +++ b/cobc/cobc.c @@ -80,13 +80,16 @@ struct strcache { }; /* Compile level */ -#define CB_LEVEL_PREPROCESS 1 -#define CB_LEVEL_TRANSLATE 2 -#define CB_LEVEL_COMPILE 3 -#define CB_LEVEL_ASSEMBLE 4 -#define CB_LEVEL_MODULE 5 -#define CB_LEVEL_LIBRARY 6 -#define CB_LEVEL_EXECUTABLE 7 +enum compile_level { + CB_LEVEL_UNSET = 0, + CB_LEVEL_PREPROCESS = 1, + CB_LEVEL_TRANSLATE = 2, + CB_LEVEL_COMPILE = 3, + CB_LEVEL_ASSEMBLE = 4, + CB_LEVEL_MODULE = 5, + CB_LEVEL_LIBRARY = 6, + CB_LEVEL_EXECUTABLE = 7 +}; /* Info display limits */ #define CB_IMSG_SIZE 24 @@ -302,7 +305,7 @@ static size_t cobc_buffer_size; static struct filename *file_list; -static unsigned int cb_compile_level = 0; +static enum compile_level cb_compile_level = 0; static int iargs; @@ -1947,17 +1950,19 @@ clean_up_intermediates (struct filename *fn, const int status) if (save_all_src) { return; } - if (fn->need_preprocess && - (status || cb_compile_level > CB_LEVEL_PREPROCESS || - (cb_compile_level == CB_LEVEL_PREPROCESS && save_temps))) { + if (fn->need_preprocess + && (status + || cb_compile_level > CB_LEVEL_PREPROCESS + || (cb_compile_level == CB_LEVEL_PREPROCESS && save_temps))) { cobc_check_action (fn->preprocess); } if (save_c_src) { return; } - if (fn->need_translate && - (status || cb_compile_level > CB_LEVEL_TRANSLATE || - (cb_compile_level == CB_LEVEL_TRANSLATE && save_temps))) { + if (fn->need_translate + && (status + || cb_compile_level > CB_LEVEL_TRANSLATE + || (cb_compile_level == CB_LEVEL_TRANSLATE && save_temps))) { cobc_check_action (fn->translate); cobc_check_action (fn->trstorage); if (fn->localfile) { @@ -2048,9 +2053,10 @@ cobc_clean_up (const int status) ylex_clear_all (); for (fn = file_list; fn; fn = fn->next) { - if (fn->need_assemble && - (status || cb_compile_level > CB_LEVEL_ASSEMBLE || - (cb_compile_level == CB_LEVEL_ASSEMBLE && save_temps))) { + if (fn->need_assemble + && (status + || cb_compile_level > CB_LEVEL_ASSEMBLE + || (cb_compile_level == CB_LEVEL_ASSEMBLE && save_temps))) { cobc_check_action (fn->object); } clean_up_intermediates (fn, status); @@ -3237,7 +3243,7 @@ process_command_line (const int argc, char **argv) case 'E': /* -E : Preprocess */ - if (cb_compile_level != 0) { + if (cb_compile_level != CB_LEVEL_UNSET) { cobc_options_error_nonfinal (); } cb_compile_level = CB_LEVEL_PREPROCESS; @@ -3245,7 +3251,7 @@ process_command_line (const int argc, char **argv) case 'C': /* -C : Generate C code */ - if (cb_compile_level != 0) { + if (cb_compile_level != CB_LEVEL_UNSET) { cobc_options_error_nonfinal (); } save_c_src = 1; @@ -3254,7 +3260,7 @@ process_command_line (const int argc, char **argv) case 'S': /* -S : Generate assembler code */ - if (cb_compile_level != 0) { + if (cb_compile_level != CB_LEVEL_UNSET) { cobc_options_error_nonfinal (); } #if defined(__TINYC__) || defined(__OS400__) @@ -3273,7 +3279,7 @@ process_command_line (const int argc, char **argv) case 'c': /* -c : Generate C object code */ - if (cb_compile_level != 0) { + if (cb_compile_level != CB_LEVEL_UNSET) { cobc_options_error_nonfinal (); } cb_compile_level = CB_LEVEL_ASSEMBLE; @@ -4010,7 +4016,7 @@ process_command_line (const int argc, char **argv) } /* set compile_level from output file if not set already */ - if (cb_compile_level == 0 + if (cb_compile_level == CB_LEVEL_UNSET && output_name != NULL) { set_compile_level_from_file_extension (output_name); } @@ -4208,10 +4214,12 @@ process_filename (const char *filename) /* Set preprocess filename */ if (!fn->need_preprocess) { fn->preprocess = cobc_main_strdup (fn->source); - } else if (output_name && cb_compile_level == CB_LEVEL_PREPROCESS) { + } else + if (output_name && cb_compile_level == CB_LEVEL_PREPROCESS) { fn->preprocess = cobc_main_strdup (output_name); - } else if (save_all_src || save_temps - || cb_compile_level == CB_LEVEL_PREPROCESS) { + } else + if (save_all_src || save_temps + || cb_compile_level == CB_LEVEL_PREPROCESS) { fn->preprocess = cobc_main_stradd_dup (fbasename, ".i"); } else { fn->preprocess = cobc_main_malloc (COB_FILE_MAX); @@ -4221,10 +4229,12 @@ process_filename (const char *filename) /* Set translate filename */ if (!fn->need_translate) { fn->translate = cobc_main_strdup (fn->source); - } else if (output_name && cb_compile_level == CB_LEVEL_TRANSLATE) { + } else + if (output_name && cb_compile_level == CB_LEVEL_TRANSLATE) { fn->translate = cobc_main_strdup (output_name); - } else if (save_all_src || save_temps || save_c_src || - cb_compile_level == CB_LEVEL_TRANSLATE) { + } else + if (save_all_src || save_temps || save_c_src + || cb_compile_level == CB_LEVEL_TRANSLATE) { fn->translate = cobc_main_stradd_dup (fbasename, ".c"); } else { fn->translate = cobc_main_malloc (COB_FILE_MAX); @@ -4260,11 +4270,15 @@ process_filename (const char *filename) /* Set object filename */ if (!fn->need_assemble) { fn->object = cobc_main_strdup (fn->source); - } else if (output_name && cb_compile_level == CB_LEVEL_ASSEMBLE) { + } else + if (output_name && cb_compile_level == CB_LEVEL_ASSEMBLE) { fn->object = cobc_main_strdup (output_name); - } else if (save_temps || cb_compile_level == CB_LEVEL_ASSEMBLE) { + } else + if (save_temps + || cb_compile_level == CB_LEVEL_ASSEMBLE) { fn->object = cobc_main_stradd_dup (fbasename, "." COB_OBJECT_EXT); - } else if (cb_compile_level != CB_LEVEL_MODULE) { + } else + if (cb_compile_level != CB_LEVEL_MODULE) { /* note: CB_LEVEL_MODULE is compiled without an intermediate object file */ fn->object = cobc_main_malloc (COB_FILE_MAX); cob_temp_name ((char *)fn->object, "." COB_OBJECT_EXT); @@ -4927,7 +4941,8 @@ preprocess (struct filename *fn) int ret; #endif - if (output_name || cb_compile_level > CB_LEVEL_PREPROCESS) { + if (output_name + || cb_compile_level > CB_LEVEL_PREPROCESS) { if (cb_unix_lf) { ppout = fopen(fn->preprocess, "wb"); } else { @@ -5561,15 +5576,14 @@ print_files_and_their_records (cb_tree file_list_p) int dummy = 1; for (l = file_list_p; l; l = CB_CHAIN (l)) { + const struct cb_file* file = CB_FILE (CB_VALUE (l)); snprintf (print_data, CB_PRINT_LEN, "%s%05d %-14.14s %s", cb_list_datamap ? " " : "", - CB_FILE (CB_VALUE (l))->record_max, - "FILE", - CB_FILE (CB_VALUE (l))->name); + file->record_max, "FILE", file->name); print_program_data (print_data); - if (CB_FILE (CB_VALUE (l))->record) { - print_fields (CB_FILE (CB_VALUE (l))->record, &dummy); + if (file->record) { + print_fields (file->record, &dummy); print_program_data (""); } } @@ -7917,8 +7931,8 @@ process_assemble (struct filename *fn) ret = process (cobc_buffer); return ret; #elif defined(__WATCOMC__) - if (cb_compile_level == CB_LEVEL_MODULE || - cb_compile_level == CB_LEVEL_LIBRARY) { + if (cb_compile_level == CB_LEVEL_MODULE + || cb_compile_level == CB_LEVEL_LIBRARY) { sprintf (cobc_buffer, "%s -c %s %s %s -fe=\"%s\" \"%s\"", cobc_cc, cobc_cflags, cobc_include, COB_PIC_FLAGS, fn->object, fn->translate); @@ -7930,9 +7944,9 @@ process_assemble (struct filename *fn) ret = process (cobc_buffer); return ret; #else - if (cb_compile_level == CB_LEVEL_MODULE || - cb_compile_level == CB_LEVEL_LIBRARY || - cb_compile_level == CB_LEVEL_ASSEMBLE) { + if (cb_compile_level == CB_LEVEL_MODULE + || cb_compile_level == CB_LEVEL_LIBRARY + || cb_compile_level == CB_LEVEL_ASSEMBLE) { sprintf (cobc_buffer, "%s -c %s %s %s -o \"%s\" \"%s\"", cobc_cc, cobc_cflags, cobc_include, COB_PIC_FLAGS, fn->object, fn->translate); @@ -8819,8 +8833,8 @@ process_file (struct filename *fn, int status) print_program_listing (); } } - if (cb_compile_level < CB_LEVEL_COMPILE || - cb_flag_syntax_only || fn->has_error) { + if (cb_compile_level < CB_LEVEL_COMPILE + || cb_flag_syntax_only || fn->has_error) { return status; } if (cb_compile_level == CB_LEVEL_COMPILE) { @@ -8830,14 +8844,15 @@ process_file (struct filename *fn, int status) return status; } - if (cb_compile_level == CB_LEVEL_MODULE && fn->need_assemble) { + if (cb_compile_level == CB_LEVEL_MODULE + && fn->need_assemble) { /* Build module direct */ fn->has_error = process_module_direct (fn); status |= fn->has_error; } else { /* Compile to object code */ - if (cb_compile_level >= CB_LEVEL_ASSEMBLE && - fn->need_assemble) { + if (cb_compile_level >= CB_LEVEL_ASSEMBLE + && fn->need_assemble) { fn->has_error = process_assemble (fn); status |= fn->has_error; } diff --git a/cobc/codegen.c b/cobc/codegen.c index cd7d8f9b4..b7b578fbc 100644 --- a/cobc/codegen.c +++ b/cobc/codegen.c @@ -4253,9 +4253,11 @@ output_param (cb_tree x, int id) case CB_TAG_INTEGER: output_integer (x); break; - case CB_TAG_STRING: - output_string (CB_STRING (x)->data, (int) CB_STRING (x)->size, 0); + case CB_TAG_STRING: { + const struct cb_string *str = CB_STRING (x); + output_string (str->data, (int) str->size, 0); break; + } case CB_TAG_LOCALE_NAME: output_param (CB_LOCALE_NAME(x)->list, id); break; @@ -5845,7 +5847,7 @@ output_initialize_one (struct cb_initialize *p, cb_tree x) case CB_USAGE_FP_DEC64: case CB_USAGE_FP_DEC128: output_initialize_fp_bindec (x, f); - return; + return; default: break; } diff --git a/cobc/flag.def b/cobc/flag.def index 29a7afeab..a3ff86884 100644 --- a/cobc/flag.def +++ b/cobc/flag.def @@ -93,7 +93,7 @@ CB_FLAG_NQ (1, "ebcdic-table", 16, /* cf cconv.h for all available tables */ _(" -febcdic-table=[DEFAULT|RESTRICTED-GC|IBM|GCOS]\tdefine EBCDIC translation table:\n" " * default: translation to extended ASCII as per MF\n" " * restricted-gc: translation from restricted ASCII only\n" - " * ibm: translation to restricted ASCII as per IBM" + " * ibm: translation to restricted ASCII as per IBM\n" " * gcos: translation to extended ASCII as per GCOS7")) /* Binary flags */ diff --git a/cobc/parser.y b/cobc/parser.y index 83bcc79c7..3bea0d0cf 100644 --- a/cobc/parser.y +++ b/cobc/parser.y @@ -14299,7 +14299,7 @@ examine_format_variant: TALLYING { cb_tree tally = cb_build_identifier (cb_build_reference ("TALLY"), 0); - cb_emit_initialize (CB_LIST_INIT (tally), NULL, cb_int0, NULL, NULL); + cb_emit_move (cb_zero, CB_LIST_INIT (tally)); cb_init_tallying (); cb_build_tallying_data (tally); } diff --git a/cobc/pplex.l b/cobc/pplex.l index cc6f72e70..026fbb4d2 100644 --- a/cobc/pplex.l +++ b/cobc/pplex.l @@ -1164,7 +1164,7 @@ ppopen (const char *name, struct cb_replace_list *replacing_list) char *s; #endif char *dname; - cb_tree x = NULL; + cb_tree x = NULL; if (ppin) { for (; newline_count > 0; newline_count--) { @@ -1181,6 +1181,8 @@ ppopen (const char *name, struct cb_replace_list *replacing_list) * ideally open first, then check if we have thy physical same file * (could also fix symlinked files) */ if (!strcmp (name, current_copy_info->dname)) { + struct cb_tree_common xc; + x = &xc; for (current_copy_info = current_copy_info->next; current_copy_info; current_copy_info = current_copy_info->prev) { int line; if (current_copy_info->prev) { @@ -1190,11 +1192,9 @@ ppopen (const char *name, struct cb_replace_list *replacing_list) } cb_inclusion_note (current_copy_info->dname, line); } - x = cobc_malloc (sizeof (struct cb_tree_common)); x->source_file = name; x->source_line = -1; cb_error_x (x, _("recursive inclusion")); - cobc_free (x); break; } @@ -1629,6 +1629,9 @@ plex_call_destroy (void) while (copy_stack) { ci = copy_stack; copy_stack = ci->next; + if (ci->dname) { + cobc_free (ci->dname); + } cobc_free (ci); } diff --git a/cobc/typeck.c b/cobc/typeck.c index 4a3681eb5..afff500d3 100644 --- a/cobc/typeck.c +++ b/cobc/typeck.c @@ -11761,12 +11761,13 @@ validate_move (cb_tree src, cb_tree dst, const unsigned int is_value, int *move_ static cb_tree cb_build_memset (cb_tree x, const int c) { + cb_tree source = cb_int (c); if (cb_field_size (x) == 1) { - return CB_BUILD_FUNCALL_2 ("$E", x, cb_int (c)); + return CB_BUILD_FUNCALL_2 ("$E", x, source); } return CB_BUILD_FUNCALL_3 ("memset", CB_BUILD_CAST_ADDRESS (x), - cb_int (c), CB_BUILD_CAST_LENGTH (x)); + source, CB_BUILD_CAST_LENGTH (x)); } static cb_tree diff --git a/libcob/ChangeLog b/libcob/ChangeLog index 02a2a5d81..a1e65840c 100644 --- a/libcob/ChangeLog +++ b/libcob/ChangeLog @@ -198,6 +198,19 @@ * fileio.c [WITH_DB] (unlock_file): extracted to match other functions * fileio.c [WITH_DB]: added extra parameters to DB_PUT, DB_GET, DB_SEQ, DB_CPUT to show what is actually used + * fileio.c: fixed some memory leaks related to filename handling + * fileio.c (cob_file_free): file was not removed from cache which + led to double-free scenarios on cleanup + * fileio.c (cob_open): fixed concattenated filenames resetting the static + filename buffer, leading to use-after-free later + * fileio.c (do_acu_hyphen_translation, copy_fcd_to_file): + fix read of invalid data + * intrinsic.c (split_around_t): fix read of invalid data + * mlio.c (copy_data_as_string): new function replacing cob_strndup_void, + doing what the callers expect, fixing read of invalid data; + added missing check for its return value in is_valid_xml_name + * mlio.c (cob_xml_generate_new): fixed memory leak when valid namespace + data and invalid namepace prefix is passed 2022-10-05 Simon Sobisch diff --git a/libcob/fbdb.c b/libcob/fbdb.c index c87a9cde2..5a006fe41 100644 --- a/libcob/fbdb.c +++ b/libcob/fbdb.c @@ -1235,6 +1235,7 @@ ix_bdb_open (cob_file_api *a, cob_file *f, char *filename, const enum cob_open_m } p = cob_malloc (sizeof (struct indexed_file)); + f->file = p; f->flag_file_lock = 0; f->curkey = -1; if (bdb_env != NULL) { @@ -1251,7 +1252,6 @@ ix_bdb_open (cob_file_api *a, cob_file *f, char *filename, const enum cob_open_m } else { lock_mode = DB_LOCK_READ; } - f->file = p; ret = bdb_lock_file (f, filename, lock_mode); if (ret) { cob_free (p); @@ -1288,6 +1288,7 @@ ix_bdb_open (cob_file_api *a, cob_file *f, char *filename, const enum cob_open_m } if (ret == -1) { /* no .dd found - just go on */ + ret = 0; } else if (ret) { return ret; } @@ -1317,7 +1318,9 @@ ix_bdb_open (cob_file_api *a, cob_file *f, char *filename, const enum cob_open_m } /* btree info */ - ret = db_create (&p->db[i], bdb_env, 0); + if (!ret) { + ret = db_create (&p->db[i], bdb_env, 0); + } if (!ret) { handle_created = 1; if (f->flag_big_endian) { diff --git a/libcob/fextfh.c b/libcob/fextfh.c index adbbdedb1..0d16560de 100644 --- a/libcob/fextfh.c +++ b/libcob/fextfh.c @@ -626,7 +626,7 @@ copy_fcd_to_file (FCD3* fcd, cob_file *f, struct fcd_file *fcd_list_entry) char *origin = (char*)f->assign->data; /* limit filename to last element after path separator, when specified */ - for (k=(int)f->assign->size; k; k--) { + for (k=(int)f->assign->size - 1; k; k--) { if (f->assign->data[k] == SLASH_CHAR #ifdef _WIN32 || f->assign->data[k] == '/' diff --git a/libcob/fileio.c b/libcob/fileio.c index 42e99b4e2..400f5364f 100644 --- a/libcob/fileio.c +++ b/libcob/fileio.c @@ -1641,12 +1641,18 @@ has_acu_hyphen (char *src) static void do_acu_hyphen_translation (char *src) { + size_t len; /* maybe store device type to "adjust locking rules" */ /* find first non-space and return it in the original storage */ for (src = src + 3; *src && isspace ((cob_u8_t)*src); src++); - - strncpy (file_open_buff, src, (size_t)COB_FILE_MAX); - file_open_buff[COB_FILE_MAX] = 0; + + len = strlen (src); + if (len >= COB_FILE_MAX) { + len = COB_FILE_MAX; + } + memcpy (file_open_buff, src, len); + file_open_buff[len + 1] = 0; + strncpy (file_open_name, file_open_buff, (size_t)COB_FILE_MAX); } @@ -4804,7 +4810,7 @@ open_next (cob_file *f) f->fd = open (f->nxt_filename, O_RDONLY); f->flag_is_concat = 0; if (f->org_filename) { - cob_cache_free (f->org_filename); + cob_free (f->org_filename); f->org_filename = NULL; } } @@ -6760,7 +6766,6 @@ cob_file_malloc (cob_file **pfl, cob_file_key **pky, void cob_file_free (cob_file **pfl, cob_file_key **pky) { - cob_file *fl; if (pky != NULL) { if (*pky != NULL) { cob_cache_free (*pky); @@ -6768,19 +6773,36 @@ cob_file_free (cob_file **pfl, cob_file_key **pky) } } if (pfl != NULL && *pfl != NULL) { - fl = *pfl; + struct file_list *fc, *prev; + cob_file *fl = *pfl; if (fl->linage) { cob_cache_free (fl->linage); fl->linage = NULL; } if (fl->org_filename) { - cob_cache_free (fl->org_filename); + cob_free (fl->org_filename); fl->org_filename = NULL; } if (fl->convert_field) { cob_free (fl->convert_field); fl->convert_field = NULL; } + + /* Remove from cache */ + prev = file_cache; + for (fc = file_cache; fc; fc =fc->next) { + if (fc->file == fl) { + if (fc == file_cache) { + file_cache = fc->next; + } else { + prev->next = fc->next; + } + cob_free (fc); + break; + } + prev = fc; + } + cob_cache_free (*pfl); *pfl = NULL; } @@ -7036,7 +7058,7 @@ cob_open (cob_file *f, const enum cob_open_mode mode, const int sharing, cob_fie || f->organization == COB_ORG_LINE_SEQUENTIAL) && (mode == COB_OPEN_INPUT || mode == COB_OPEN_I_O) - && (cp = strchr(file_open_name,file_setptr->cob_concat_sep[0])) != NULL + && (cp = strchr (file_open_name, file_setptr->cob_concat_sep[0])) != NULL && file_open_name[0] != '>' && file_open_name[0] != '<' && file_open_name[0] != '|') { @@ -7044,7 +7066,7 @@ cob_open (cob_file *f, const enum cob_open_mode mode, const int sharing, cob_fie f->org_filename = cob_strdup (file_open_name); f->nxt_filename = strchr(f->org_filename,file_setptr->cob_concat_sep[0]); *f->nxt_filename++ = 0; - file_open_name = f->org_filename; + strcpy (file_open_name, f->org_filename); } if (!f->flag_optional diff --git a/libcob/fsqlxfd.c b/libcob/fsqlxfd.c index 2a186129b..225381f6e 100644 --- a/libcob/fsqlxfd.c +++ b/libcob/fsqlxfd.c @@ -27,7 +27,7 @@ int cob_findkey_attr (cob_file *f, cob_field *kf, int *fullkeylen, int *partlen) { - int k,part; + int k, part; *fullkeylen = *partlen = 0; for (k = 0; k < f->nkeys; ++k) { diff --git a/libcob/intrinsic.c b/libcob/intrinsic.c index 2205819c2..2f9485dea 100644 --- a/libcob/intrinsic.c +++ b/libcob/intrinsic.c @@ -2602,7 +2602,7 @@ split_around_t (const char *str, char *first, char *second) } /* If there is anything after 'T', copy it into second (if present) */ - if (second != NULL) { + if (second != NULL && str[i]) { str += i + 1; second_length = strlen (str); if (second_length == 0) { diff --git a/libcob/mlio.c b/libcob/mlio.c index 1c3568d7d..0097d6aff 100644 --- a/libcob/mlio.c +++ b/libcob/mlio.c @@ -220,11 +220,19 @@ is_empty (const cob_field * const f) return 1; } -/* strdup wrapper for get_trimmed_data */ +/* strdup-like wrapper for get_trimmed_data, returns a pointer to + fresh allocated memory pointing to a copy of the specified + data with specified size as string (+ trailing NULL) */ static void * -cob_strndup_void (const char* str, const size_t size) +copy_data_as_string (const char* data, const size_t size) { - return (void*)cob_strndup (str, size); + char *ptr = cob_malloc (size + 1); + if (!ptr) { + return NULL; + } + memcpy (ptr, data, size); + ptr[size] = 0; + return (void *)ptr; } /* returns a duplicate of the given cob_field's data, @@ -245,7 +253,7 @@ get_trimmed_data (const cob_field * const f, if (COB_FIELD_JUSTIFIED (f)) { for (; *str == ' ' && len > 1; ++str, --len); } else { - for (; str[len - 1] == ' ' && len > 1; --len); + for (; (str[len - 1] == ' ' || str[len - 1] == 0) && len > 1; --len); } return (*strndup_func)(str, len); @@ -284,7 +292,11 @@ is_valid_xml_name (const cob_field * const f) return 0; } - str = get_trimmed_data (f, &cob_strndup_void); + str = get_trimmed_data (f, ©_data_as_string); + if (!str) { + /* likely should raise an exception */ + return 0; + } ret = 1; for (c = str + 1; *c; ++c) { @@ -966,7 +978,7 @@ cob_xml_generate (cob_field *out, cob_ml_tree *tree, cob_field *count, set_xml_exception (XML_INVALID_NAMESPACE); return; } else { - ns_data = get_trimmed_data (ns, &cob_strndup_void); + ns_data = get_trimmed_data (ns, ©_data_as_string); if (!cob_is_valid_uri (ns_data)) { set_xml_exception (XML_INVALID_NAMESPACE); cob_free ((void *)ns_data); @@ -981,6 +993,9 @@ cob_xml_generate (cob_field *out, cob_ml_tree *tree, cob_field *count, if (is_empty (ns_prefix)) { ns_prefix = NULL; } else if (!is_valid_xml_name (ns_prefix)) { + if (ns_data) { + cob_free ((void *)ns_data); + } set_xml_exception (XML_INVALID_NAMESPACE_PREFIX); return; } diff --git a/tests/testsuite.src/run_misc.at b/tests/testsuite.src/run_misc.at index 50de0b9a9..4e27cacf4 100644 --- a/tests/testsuite.src/run_misc.at +++ b/tests/testsuite.src/run_misc.at @@ -4568,33 +4568,33 @@ main (int argc, char **argv) case 0: /* program coming back */ /* Clean up and terminate runtime */ - cob_runtime_hint("program exited with return code %d", + cob_runtime_hint ("program exited with return code %d", cob_last_exit_code ()); cob_tidy (); break; case 1: /* normal exit */ - cob_runtime_hint("STOP RUN with return code %d", + cob_runtime_hint ("STOP RUN with return code %d", cob_last_exit_code ()); break; case -1: /* error exit */ - cob_runtime_hint("error exit with return code %d and error \"%s\"", + cob_runtime_hint ("error exit with return code %d and error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; case -2: /* hard error exit */ - cob_runtime_hint("hard error exit with return code %d and error \"%s\"", + cob_runtime_hint ("hard error exit with return code %d and error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; case -3: /* signal handler exit */ - cob_runtime_hint("signal handler exit with signal %d and error \"%s\"", + cob_runtime_hint ("signal handler exit with signal %d and error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; default: - cob_runtime_hint("unexpected return from cob_call_with_exception_check, " + cob_runtime_hint ("unexpected return from cob_call_with_exception_check, " "last exit code %d, last error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; @@ -4614,14 +4614,14 @@ AT_CHECK([$COBCRUN_DIRECT ./caller callee 42], [0], [P1: A], AT_CHECK([$COBCRUN_DIRECT ./caller callee2], [0], [STOP WITH 2], [note: STOP RUN with return code 2 ]) -AT_CHECK([$COBCRUN_DIRECT ./caller buggy], [0], [out of bounds - refmod following], -[libcob: buggy.cob:10: error: offset of 'VAR' out of bounds: 2, maximum: 1 -note: error exit with return code -1 and error "buggy.cob:10: offset of 'VAR' out of bounds: 2, maximum: 1" -]) AT_CHECK([$COBCRUN_DIRECT ./caller notthere], [0], [], [libcob: error: module 'notthere' not found note: error exit with return code -1 and error "module 'notthere' not found" ]) +AT_CHECK([$COBCRUN_DIRECT ./caller buggy], [0], [out of bounds - refmod following], +[libcob: buggy.cob:10: error: offset of 'VAR' out of bounds: 2, maximum: 1 +note: error exit with return code -1 and error "buggy.cob:10: offset of 'VAR' out of bounds: 2, maximum: 1" +]) AT_CLEANUP