From 6427fd3f2fc192a76c257b0772b175daaa2b3d07 Mon Sep 17 00:00:00 2001 From: arnab8335 <1904017@kiit.ac.in> Date: Sun, 30 Aug 2026 20:59:58 +0530 Subject: [PATCH 1/2] libcob: implement dynamic high-water mark screen_term_buff to prevent overflow --- libcob/common.h | 3 + libcob/screenio.c | 103 ++++++++++++++++------- tests/testsuite.src/run_manual_screen.at | 40 +++++++++ 3 files changed, 117 insertions(+), 29 deletions(-) diff --git a/libcob/common.h b/libcob/common.h index 7657d624a..a2970a3fa 100644 --- a/libcob/common.h +++ b/libcob/common.h @@ -665,6 +665,9 @@ typedef __mpz_struct mpz_t[1]; TODO: add compiler configuration for limiting this */ #define COB_MAX_SUBSCRIPTS 16 +/* Maximum Buffer Warning Size */ +#define COB_TERM_BUFF_WARN_SIZE 32768 + /* Memory size for sorting */ #define COB_SORT_MEMORY 128 * 1024 * 1024 #define COB_SORT_CHUNK 256 * 1024 diff --git a/libcob/screenio.c b/libcob/screenio.c index d38aeca17..d9e5d65ca 100644 --- a/libcob/screenio.c +++ b/libcob/screenio.c @@ -191,7 +191,9 @@ static int pending_accept; static int got_sys_char; static int save_cursor_x = 0; static int save_cursor_y = 0; -static WINDOW *mywin; +static WINDOW *mywin; +static char *screen_term_buff = NULL; +static size_t screen_buffer_size = 0; #ifdef WITH_PANELS #define MAX_PANELS 20 @@ -3530,6 +3532,39 @@ field_display (cob_field *f, cob_flags_t fattr, const int line, const int column refresh_mywin (mywin); } +static char * +ensure_buffer (size_t requested_size) +{ + if (screen_buffer_size == 0) { + screen_buffer_size = COB_MINI_BUFF; + } + + if (requested_size > screen_buffer_size) { + if (requested_size > COB_TERM_BUFF_WARN_SIZE) { + cob_runtime_warning (_("ACCEPT/DISPLAY of unusually large field (%lu bytes)"), + (unsigned long)requested_size); + } + + /* Expanding the Buffer */ + char *tmp = realloc (screen_term_buff, requested_size); + if (tmp == NULL) { + cob_runtime_error (_("could not allocate %lu bytes of memory"), + (unsigned long)requested_size); + return screen_term_buff; + } + screen_term_buff = tmp; + screen_buffer_size = requested_size; + } else if (screen_term_buff == NULL) { + screen_term_buff = realloc (screen_term_buff, screen_buffer_size); + if (screen_term_buff == NULL) { + cob_runtime_error (_("could not allocate %lu bytes of memory"), + (unsigned long)screen_buffer_size); + } + } + + return screen_term_buff; +} + static void field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolumn, cob_field *fgc, cob_field *bgc, cob_field *fscroll, cob_field *ftimeout, @@ -3538,6 +3573,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum { unsigned char *p; unsigned char *p2; + unsigned char *term_buff; size_t count; int keyp; int fret = 0; @@ -3612,15 +3648,20 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum } else { size_accept = f->size; } + term_buff = (unsigned char *)ensure_buffer (size_accept); + if (screen_buffer_size < size_accept) { + /* allocation failure */ + return; + } - p = COB_TERM_BUFF; - temp_field.data = COB_TERM_BUFF; + p = term_buff; + temp_field.data = term_buff; temp_field.attr = &const_alpha_attr; temp_field.size = size_accept; if (fattr & COB_SCREEN_UPDATE) { - cob_move (f, &temp_field); /* updates COB_TERM_BUFF */ + cob_move (f, &temp_field); /* updates term_buff */ } else { - memset (COB_TERM_BUFF, ' ', size_accept); + memset (term_buff, ' ', size_accept); } raise_ec_on_truncation (size_accept); @@ -3657,7 +3698,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum cursor_off = cob_get_int (cursor); if (cursor_off >= 1) { /* max: last_position with data */ - int last_data = p_set - COB_TERM_BUFF + 1; + int last_data = p_set - term_buff + 1; if (last_data < cursor_off) { cursor_off = last_data; } @@ -3694,7 +3735,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum accept_cursor_x = scolumn + size_accept; right_pos = scolumn + size_accept - 1; - p = COB_TERM_BUFF; + p = term_buff; } else { right_pos = 0; p = NULL; @@ -3721,7 +3762,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum } for (count = right_pos; (int)count > scolumn - 1; count--) { /* Get character */ - p2 = COB_TERM_BUFF + count - scolumn; + p2 = term_buff + count - scolumn; move_char = *p2; /* Field prompts. */ if (COB_FIELD_IS_NUMERIC (f)) { @@ -3902,10 +3943,10 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Shift remainder left with cursor. */ for (count = ccolumn; count < right_pos + 1; count++) { /* Get character. */ - p2 = COB_TERM_BUFF + count - scolumn ; + p2 = term_buff + count - scolumn ; move_char = *p2; /* Move the character left. */ - p2 = COB_TERM_BUFF + count - scolumn - 1; + p2 = term_buff + count - scolumn - 1; *p2 = move_char; /* Update screen with moved character. */ cob_move_cursor (cline, count - 1); @@ -3918,7 +3959,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum } } /* Put space as the right most character. */ - p2 = COB_TERM_BUFF + size_accept - 1; + p2 = term_buff + size_accept - 1; if (fattr & COB_SCREEN_NO_ECHO) { *p2 = COB_CH_SP; } else if (COB_FIELD_IS_NUMERIC (f)) { @@ -3942,7 +3983,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Find non-blank character left to right. */ for (count = scolumn; count <= right_pos; count++) { /* Get character. */ - p2 = COB_TERM_BUFF + count - scolumn; + p2 = term_buff + count - scolumn; move_char = *p2; /* Stop at beginning non-blank character. */ if (move_char != ' ') { @@ -3958,11 +3999,11 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Cursor to start of characters. */ ccolumn = count; cob_move_cursor (cline, ccolumn); - p = COB_TERM_BUFF + ccolumn - scolumn; + p = term_buff + ccolumn - scolumn; } else { /* Cursor to start of field. */ cob_move_cursor (sline, scolumn); - p = COB_TERM_BUFF; + p = term_buff; } /* Reset */ at_eof = 0; @@ -3974,7 +4015,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Find non-blank character right to left. */ for (count = right_pos; (int) count >= scolumn; count--) { /* Get character. */ - p2 = COB_TERM_BUFF + count - scolumn; + p2 = term_buff + count - scolumn; move_char = *p2; /* Stop at ending non-blank character. */ if (move_char != ' ') { @@ -3995,11 +4036,11 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Cursor after end character. */ ccolumn = count; cob_move_cursor (cline, ccolumn); - p = COB_TERM_BUFF + ccolumn - scolumn; + p = term_buff + ccolumn - scolumn; } else { /* Cursor to end of size of field */ cob_move_cursor (sline, right_pos); - p = COB_TERM_BUFF + size_accept - 1; + p = term_buff + size_accept - 1; } /* Reset */ at_eof = 0; @@ -4012,7 +4053,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum if ((int) ccolumn > scolumn) { ccolumn--; cob_move_cursor (cline, ccolumn); - p = COB_TERM_BUFF + ccolumn - scolumn; + p = term_buff + ccolumn - scolumn; continue; } /* End of field, auto-skip, return left-arrow. */ @@ -4029,7 +4070,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum if (ccolumn < right_pos) { ccolumn++; cob_move_cursor (cline, ccolumn); - p = COB_TERM_BUFF + ccolumn - scolumn; + p = term_buff + ccolumn - scolumn; continue; } /* End of field, auto-skip, return right-arrow. */ @@ -4048,10 +4089,10 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Delete character, move remainder left. */ for (count = ccolumn; count < right_pos; count++) { /* Get character one position to right. */ - p2 = COB_TERM_BUFF + count - scolumn + 1; + p2 = term_buff + count - scolumn + 1; move_char = *p2; /* Move the character left. */ - p2 = COB_TERM_BUFF + count - scolumn; + p2 = term_buff + count - scolumn; *p2 = move_char; /* Update screen with moved character. */ cob_move_cursor (cline, count); @@ -4064,7 +4105,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum } } /* Put space as the right most character. */ - p2 = COB_TERM_BUFF + size_accept - 1; + p2 = term_buff + size_accept - 1; if (fattr & COB_SCREEN_NO_ECHO) { *p2 = COB_CH_SP; } else if (COB_FIELD_IS_NUMERIC (f)) { @@ -4079,7 +4120,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Alt-Delete key, erase cursor to end of field. */ for (count = ccolumn; count <= right_pos; count++) { /* Character position. */ - p2 = COB_TERM_BUFF + count - scolumn; + p2 = term_buff + count - scolumn; /* Blank character. */ if (fattr & COB_FIELD_IS_NUMERIC (f)) { move_char = '0'; @@ -4119,7 +4160,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum && mcolumn <= (int)right_pos) { ccolumn = mcolumn; cob_move_cursor (cline, ccolumn); - p = COB_TERM_BUFF + ccolumn - scolumn; + p = term_buff + ccolumn - scolumn; continue; } } @@ -4169,7 +4210,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum if (cob_field_is_numeric_or_numeric_edited (f)) { p2 = (unsigned char *)" "; } else { - p2 = COB_TERM_BUFF + right_pos - scolumn; + p2 = term_buff + right_pos - scolumn; } if (*p2 != ' ') { cob_beep (); @@ -4178,10 +4219,10 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum /* Move remainder to the right. */ for (count = right_pos; count > ccolumn; count--) { /* Get character */ - p2 = COB_TERM_BUFF + count - scolumn - 1; + p2 = term_buff + count - scolumn - 1; move_char = *p2; /* Move character one right. */ - p2 = COB_TERM_BUFF + count - scolumn; + p2 = term_buff + count - scolumn; *p2 = move_char; /* Update screen with moved character. */ if ((int) count > scolumn) { @@ -4254,7 +4295,7 @@ field_accept (cob_field *f, cob_flags_t fattr, const int sline, const int scolum cob_move (&temp_field, f); cob_move_cursor (sline, right_pos + 1); #if 0 /* possible cleanup to not "leak" input data */ - memset (COB_TERM_BUFF, ' ', size_accept); + memset (term_buff, ' ', size_accept); #endif } refresh_mywin (mywin); @@ -4713,6 +4754,11 @@ cob_exit_screen (void) cob_free (cob_base_inp); cob_base_inp = NULL; } + if (screen_term_buff) { + free (screen_term_buff); + screen_term_buff = NULL; + screen_buffer_size = 0; + } } COB_ACCEPT_STATUS = 0; cobglobptr = NULL; @@ -5681,7 +5727,6 @@ sys_window_delete (PPARM_FLD parm) return 0; } - /* LIST_WINDOW - list all of the windows */ static void sys_window_list (PLIST_FLD list, size_t amount) diff --git a/tests/testsuite.src/run_manual_screen.at b/tests/testsuite.src/run_manual_screen.at index e2506bc34..9db15dc09 100644 --- a/tests/testsuite.src/run_manual_screen.at +++ b/tests/testsuite.src/run_manual_screen.at @@ -4159,3 +4159,43 @@ AT_CHECK([$COMPILE prog.cob], [0], [], []) MANUAL_CHECK([$COBCRUN_DIRECT ./prog], [0], [], []) AT_CLEANUP + + +AT_SETUP([ACCEPT field larger than internal I/O buffer]) +AT_KEYWORDS([screen accept]) + +AT_SKIP_IF([test "$COB_HAS_CURSES" != "yes"]) + +# regression test: the internal screen I/O buffer used to be a fixed +# 8192 bytes (COB_MEDIUM_BUFF); ACCEPTing into a field larger than that +# overflowed it. The buffer now grows on demand, so this must complete +# (and not crash) for a field well past that old limit. +AT_DATA([prog.cob], [ + IDENTIFICATION DIVISION. + PROGRAM-ID. prog. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 big-field PIC X(9000). + + SCREEN SECTION. + 01 scr. + 03 LINE 1 VALUE + 'Type a few characters, then press ENTER.'. + 03 LINE 3 COL 1 PIC X(9000) USING big-field. + + PROCEDURE DIVISION. + DISPLAY scr + ACCEPT scr + + IF COB-CRT-STATUS = 0 + GOBACK RETURNING 0 + ELSE + GOBACK RETURNING 1 + END-IF + . +]) + +AT_CHECK([$COMPILE prog.cob], [0], [], []) +MANUAL_CHECK([$COBCRUN_DIRECT ./prog], [0], [], []) + +AT_CLEANUP From 8ff350f21d56cdee3860ac505e724dba46fc879b Mon Sep 17 00:00:00 2001 From: arnab8335 <1904017@kiit.ac.in> Date: Mon, 31 Aug 2026 00:01:52 +0530 Subject: [PATCH 2/2] libcob: resolve formatting and compiler warning checks --- libcob/screenio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libcob/screenio.c b/libcob/screenio.c index d9e5d65ca..af6786f88 100644 --- a/libcob/screenio.c +++ b/libcob/screenio.c @@ -3540,13 +3540,15 @@ ensure_buffer (size_t requested_size) } if (requested_size > screen_buffer_size) { + char *tmp; + if (requested_size > COB_TERM_BUFF_WARN_SIZE) { cob_runtime_warning (_("ACCEPT/DISPLAY of unusually large field (%lu bytes)"), (unsigned long)requested_size); } /* Expanding the Buffer */ - char *tmp = realloc (screen_term_buff, requested_size); + tmp = realloc (screen_term_buff, requested_size); if (tmp == NULL) { cob_runtime_error (_("could not allocate %lu bytes of memory"), (unsigned long)requested_size);