From f443063d3bc23b202bf9468e273f228578a81b09 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 20 May 2026 05:25:38 -0400 Subject: [PATCH] Import Fixes: #348 Make adjustments to groupinfo struct; Misc tweaks to code using groupinfo items; Move group_array from stack to heap; Calloc adequate memory for it; Switch to strncpy to fix potential issues with large strings copying OOB and crashing; --- include/dsd.h | 6 +++--- src/dmr_flco.c | 2 +- src/dsd_import.c | 42 +++++++++++++++++++++++++++++++----------- src/dsd_main.c | 4 +++- src/nxdn_element.c | 2 +- 5 files changed, 39 insertions(+), 17 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index 689dee9..1b9144c 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -173,8 +173,8 @@ typedef struct pa_devicelist typedef struct { unsigned long int groupNumber; - char groupMode[8]; //char *? - char groupName[50]; + char groupMode[3]; + char groupName[100]; } groupinfo; @@ -871,7 +871,7 @@ typedef struct //trunking group and lcn freq list long int trunk_lcn_freq[26]; //max number on an EDACS system, should be enough on DMR too hopefully long int trunk_chan_map[0xFFFF]; //NXDN - 10 bit; P25 - 16 bit; DMR up to 12 bit (standard TIII) - groupinfo group_array[0x3FF]; //max supported by Cygwin is 3FFF, I hope nobody actually tries to import this many groups + groupinfo * group_array; unsigned int group_tally; //tally number of groups imported from CSV file for referencing later int lcn_freq_count; int lcn_freq_roll; //number we have 'rolled' to in search of the CC diff --git a/src/dmr_flco.c b/src/dmr_flco.c index 604df5c..76840f5 100644 --- a/src/dmr_flco.c +++ b/src/dmr_flco.c @@ -560,7 +560,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C if (opts->p25_trunk == 1 && opts->trunk_tune_enc_calls == 0) //&& type != 2 { int i, lo = 0; - uint32_t t = 0; char gm[8]; char gn[50]; + uint32_t t = 0; char gm[3]; char gn[100]; //check to see if this group already exists, or has already been locked out, or is allowed for (i = 0; i <= state->group_tally; i++) diff --git a/src/dsd_import.c b/src/dsd_import.c index 47a619f..0260881 100644 --- a/src/dsd_import.c +++ b/src/dsd_import.c @@ -7,26 +7,31 @@ int csvGroupImport(dsd_opts * opts, dsd_state * state) { char filename[1024] = "filename.csv"; sprintf (filename, "%s", opts->group_in_file); - //filename[1023] = '\0'; //necessary? + char buffer[BSIZE]; FILE * fp; fp = fopen(filename, "r"); - if (fp == NULL) { + + if (fp == NULL) + { printf("Unable to open group file '%s'\n", filename); exit(1); } + int row_count = 0; int field_count = 0; - long int group_number = 0; //local group number for array index value - UNUSED(group_number); - int i = 0; - while (fgets(buffer, BSIZE, fp)) { + + unsigned int i = 0; + while (fgets(buffer, BSIZE, fp)) + { + field_count = 0; row_count++; if (row_count == 1) continue; //don't want labels char * field = strtok(buffer, ","); //seperate by comma - while (field) { + while (field) + { if (field_count == 0) { @@ -34,23 +39,38 @@ int csvGroupImport(dsd_opts * opts, dsd_state * state) state->group_array[i].groupNumber = atol(field); fprintf (stderr, "%ld, ", state->group_array[i].groupNumber); } - if (field_count == 1) + else if (field_count == 1) { - strcpy(state->group_array[i].groupMode, field); + // strcpy(state->group_array[i].groupMode, field); + strncpy(state->group_array[i].groupMode, field, 2); //only copy two letters max A, B, D, DE fprintf (stderr, "%s, ", state->group_array[i].groupMode); } - if (field_count == 2) + else if (field_count == 2) { - strcpy(state->group_array[i].groupName, field); + // strcpy(state->group_array[i].groupName, field); + strncpy(state->group_array[i].groupName, field, 98); //this should also fix potential issues observed in past when there is no comma after the name + + uint16_t len = strlen((const char*)state->group_array[i].groupName); + + //remove any potential linebreaks at this point + if (state->group_array[i].groupName[len-1] == '\n') + { + // fprintf(stderr, " ** LEN: %d; ** ", len); //debug + state->group_array[i].groupName[len-1] = '\0'; + } + fprintf (stderr, "%s ", state->group_array[i].groupName); } field = strtok(NULL, ","); field_count++; } + fprintf (stderr, "\n"); + i++; state->group_tally++; + } fclose(fp); return 0; diff --git a/src/dsd_main.c b/src/dsd_main.c index 9fb4b31..288ee66 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -1187,7 +1187,9 @@ //trunking memset (state->trunk_lcn_freq, 0, sizeof(state->trunk_lcn_freq)); memset (state->trunk_chan_map, 0, sizeof(state->trunk_chan_map)); - state->group_tally = 0; + //allocate max 24-bit address w/ memory with zero fill (termination) for end of strings, import will only copy 98, leaving the terminator intact + state->group_array = calloc(16778000, sizeof(groupinfo)); + state->group_tally = 0; //is an unsigned int state->lcn_freq_count = 0; //number of frequncies imported as an enumerated lcn list state->lcn_freq_roll = 0; //needs reset if sync is found? state->last_cc_sync_time = time(NULL); diff --git a/src/nxdn_element.c b/src/nxdn_element.c index 331c9f3..9653c3c 100644 --- a/src/nxdn_element.c +++ b/src/nxdn_element.c @@ -1648,7 +1648,7 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) if (opts->p25_trunk == 1 && opts->trunk_tune_enc_calls == 0 && MessageType == 0x1 && state->dmr_encL == 1) { int i, lo = 0; - uint16_t t = 0; char gm[8]; char gn[50]; + uint16_t t = 0; char gm[3]; char gn[100]; //check to see if this group already exists, or has already been locked out, or is allowed for (i = 0; i <= state->group_tally; i++)