Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/rrdCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ typedef struct mbuffer {
bool inDynamic;
bool appendMode;
deepsleep_event_et dsEvent;
char *suffix; // Holds the suffix split from issue type string, if any
} data_buf;

/*Structure for Message Header*/
Expand Down
78 changes: 73 additions & 5 deletions src/rrdEventProcess.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,35 @@ void processIssueTypeEvent(data_buf *rbuf)
cmdBuff = (data_buf *)malloc(sizeof(data_buf));
if (cmdBuff)
{
dataMsgLen = strlen(cmdMap[index]) + 1;
char base[128] = {0};
char local_suffix[128] = {0};
split_issue_type(cmdMap[index], base, sizeof(base), local_suffix, sizeof(local_suffix));
if (base[0] == '\0')
{
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Empty issue type after parsing token [%s], skipping... \n", __FUNCTION__, __LINE__, cmdMap[index]);
free(cmdBuff);
cmdBuff = NULL;
if (cmdMap[index])
{
free(cmdMap[index]);
cmdMap[index] = NULL;
}
continue;
}
removeSpecialCharacterfromIssueTypeList(base);
if (base[0] == '\0')
{
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Empty base after sanitization for token [%s], skipping... \n", __FUNCTION__, __LINE__, cmdMap[index]);
free(cmdBuff);
cmdBuff = NULL;
if (cmdMap[index])
{
free(cmdMap[index]);
cmdMap[index] = NULL;
}
continue;
}
dataMsgLen = strlen(base) + 1;
RRD_data_buff_init(cmdBuff, EVENT_MSG, RRD_DEEPSLEEP_INVALID_DEFAULT); /* Setting Deafult Values*/
cmdBuff->inDynamic = rbuf->inDynamic;
if(cmdBuff->inDynamic)
Expand All @@ -88,9 +116,19 @@ void processIssueTypeEvent(data_buf *rbuf)
}
cmdBuff->appendMode = rbuf->appendMode;
cmdBuff->mdata = (char *)calloc(1, dataMsgLen);

/* Store suffix for this issue type */
cmdBuff->suffix = NULL;
if (local_suffix[0] != '\0') {
cmdBuff->suffix = strdup(local_suffix);
if (cmdBuff->suffix == NULL)
{
RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Failed to allocate memory for suffix... \n", __FUNCTION__, __LINE__);
}
}
if (cmdBuff->mdata)
{
strncpy((char *)cmdBuff->mdata, cmdMap[index], dataMsgLen);
strncpy((char *)cmdBuff->mdata, base, dataMsgLen);
processIssueType(cmdBuff);
}
else
Expand All @@ -99,6 +137,11 @@ void processIssueTypeEvent(data_buf *rbuf)
}
if(cmdBuff)
{
if (cmdBuff->suffix)
{
free(cmdBuff->suffix);
cmdBuff->suffix = NULL;
}
free(cmdBuff);
cmdBuff = NULL;
}
Expand Down Expand Up @@ -392,7 +435,10 @@ static void processIssueTypeInStaticProfile(data_buf *rbuf, issueNodeData *pIssu
#if !defined(GTEST_ENABLE)
jsonParsed = readAndParseJSON(RRD_JSON_FILE);
#else
jsonParsed = readAndParseJSON(rbuf->jsonPath);
if (rbuf->jsonPath != NULL)
{
jsonParsed = readAndParseJSON(rbuf->jsonPath);
}
#endif
if (jsonParsed == NULL)
{ // Static Profile JSON Parsing or Read Fail
Expand Down Expand Up @@ -555,6 +601,29 @@ static void processIssueTypeInInstalledPackage(data_buf *rbuf, issueNodeData *pI
suffixlen = strlen(RDM_PKG_SUFFIX);
dynJSONPath = (char *)malloc(persistentAppslen + prefixlen + suffixlen + strlen(pIssueNode->Node) + rrdjsonlen + 1);
#else
if ((rbuf == NULL) || (rbuf->jsonPath == NULL))
{
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: jsonPath is NULL, skipping installed package check... \n", __FUNCTION__, __LINE__);
if (rbuf != NULL)
{
if (rbuf->mdata != NULL)
{
free(rbuf->mdata);
rbuf->mdata = NULL;
}
if (rbuf->suffix != NULL)
{
free(rbuf->suffix);
rbuf->suffix = NULL;
}
if (rbuf->jsonPath != NULL)
{
free(rbuf->jsonPath);
rbuf->jsonPath = NULL;
}
}
return;
}
int utjsonlen = strlen(rbuf->jsonPath);
dynJSONPath = (char *)malloc(utjsonlen + 1);
#endif
Expand Down Expand Up @@ -639,7 +708,7 @@ static void removeSpecialCharacterfromIssueTypeList(char *str)

while (str[source] != '\0')
{
if (isalnum(str[source]) || str[source] == ',' || str[source] == '.')
if (isalnum(str[source]) || str[source] == ',' || str[source] == '.')
{
str[destination] = str[source];
++destination;
Expand All @@ -663,7 +732,6 @@ static int issueTypeSplitter(char *input_str, const char delimeter, char ***args
int cnt = 1, i = 0;
char *str = input_str;

removeSpecialCharacterfromIssueTypeList(str);
while (*str == delimeter)
str++;

Expand Down
5 changes: 5 additions & 0 deletions src/rrdInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ void RRD_data_buff_init(data_buf *sbuf, message_type_et sndtype, deepsleep_event
sbuf->inDynamic = false;
sbuf->appendMode = false;
sbuf->dsEvent = deepSleepEvent;
sbuf->suffix = NULL;
}

/*Function: RRD_data_buff_deAlloc
Expand All @@ -295,6 +296,10 @@ void RRD_data_buff_deAlloc(data_buf *sbuf)
{
free(sbuf->jsonPath);
}
if (sbuf->suffix)
{
free(sbuf->suffix);
}
free(sbuf);
}
}
Expand Down
135 changes: 134 additions & 1 deletion src/rrdJsonParser.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
/* Maximum suffix length, including the leading '_' character. */
#define RRD_MAX_SUFFIX_LEN 9

/*
* @function removeSpecialChar
Expand All @@ -46,6 +48,102 @@ void removeSpecialChar(char *str)
}
}


/*
* @function split_issue_type
* @brief Utility to split base and suffix from issue type string.
* The input is always split at the first '_'. The base is the part
* before the underscore (never contains '_'). The suffix is only
* kept when its total length (including the leading '_') is at most
* RRD_MAX_SUFFIX_LEN (9) characters; longer suffixes are discarded.
* After length validation the suffix is sanitized: only the characters
* [A-Za-z0-9_-] are retained so that the value is safe to use in file
* names and shell command arguments without risk of injection.
* If no underscore is present the full input is the base.
* Examples:
* "Device.DeviceTime_ab12345" → base="Device.DeviceTime",
* suffix="_ab12345" (8 chars, accepted)
* "Device.DeviceTime_Search-uuid-very-long"
* → base="Device.DeviceTime",
* suffix="" (>9 chars, discarded)
* "Device.DeviceTime" → base="Device.DeviceTime",
* suffix=""
* "Device.DeviceTime_ab;rm" → base="Device.DeviceTime",
* suffix="_abrm" (unsafe ';' stripped)
* @param const char *input - The input string to split.
* @param char *base - Buffer to store the base part (never contains '_').
* @param size_t base_len - Size of the base buffer.
* @param char *suffix - Buffer to store the suffix part when valid, else "".
* @param size_t suffix_len - Size of the suffix buffer.
* @return void
*/

void split_issue_type(const char *input, char *base, size_t base_len, char *suffix, size_t suffix_len)
{
if (base && base_len > 0)
{
base[0] = '\0';
}
if (suffix && suffix_len > 0)
{
suffix[0] = '\0';
}

if (!input || !base || !suffix)
{
return;
}

if (base_len == 0 || suffix_len == 0)
{
return;
}

const char *underscore = strchr(input, '_');
if (underscore)
{
/* Always split at the first underscore — base never contains '_' */
size_t b_len = (size_t)(underscore - input);
if (b_len >= base_len) b_len = base_len - 1;
strncpy(base, input, b_len);
base[b_len] = '\0';

/* Keep the suffix only when its total length (including '_') is
* within the allowed limit; longer tokens are discarded. */
if (strlen(underscore) <= RRD_MAX_SUFFIX_LEN)
{
/* Sanitize: retain only [A-Za-z0-9_-] to prevent injection when
* the suffix is later embedded in file names or command arguments. */
size_t si = 0, di = 0;
size_t max_copy = suffix_len - 1;
while (underscore[si] != '\0' && di < max_copy)
{
char ch = underscore[si];
if (isalnum((unsigned char)ch) || ch == '_' || ch == '-')
{
suffix[di++] = ch;
}
si++;
}
suffix[di] = '\0';
}
else
{
RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Suffix after '%s' exceeds max length (%zu > %d); discarding\n",
__FUNCTION__, __LINE__, base, strlen(underscore), RRD_MAX_SUFFIX_LEN);
suffix[0] = '\0';
}
}
else
{
/* No underscore — full input is the base */
strncpy(base, input, base_len - 1);
base[base_len - 1] = '\0';
suffix[0] = '\0';
}
}


/*
* @function getParamcount
* @brief Calculates the total number of nodes (elements) in the input string, excluding delimiters.
Expand Down Expand Up @@ -515,7 +613,11 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf
{
RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: Memory allocation failed for rfcbuf\n",__FUNCTION__,__LINE__);
free(buff->mdata); // free rfc data
buff->mdata = NULL;
free(buff->jsonPath); // free rrd path info
buff->jsonPath = NULL;
free(buff->suffix); // free suffix
buff->suffix = NULL;
return;
}

Expand All @@ -535,7 +637,11 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf
RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: %s Directory creation failed!!!\n",__FUNCTION__,__LINE__,outdir);
free(rfcbuf); // free duplicated rfc data
free(buff->mdata); // free rfc data
buff->mdata = NULL;
free(buff->jsonPath); // free rrd path info
buff->jsonPath = NULL;
free(buff->suffix); // free suffix
buff->suffix = NULL;
return;
}
else
Expand Down Expand Up @@ -576,7 +682,26 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf
else
{
RDK_LOG(RDK_LOG_DEBUG,LOG_REMDEBUG,"[%s:%d]: Continue uploading Debug Report for %s from %s... \n",__FUNCTION__,__LINE__,buff->mdata,outdir);
status = uploadDebugoutput(outdir,buff->mdata);
// Use the persisted suffix from buff for upload
char tarName[512] = {0};
int tar_name_len = 0;
if (buff->suffix && buff->suffix[0] != '\0')
{
tar_name_len = snprintf(tarName, sizeof(tarName), "%s%s", buff->mdata, buff->suffix);
}
else
{
tar_name_len = snprintf(tarName, sizeof(tarName), "%s", buff->mdata);
}
if ((tar_name_len < 0) || ((size_t)tar_name_len >= sizeof(tarName)))
{
RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: Failed to build upload file name for %s. snprintf result:%d, buffer size:%zu\n", __FUNCTION__,__LINE__,buff->mdata,tar_name_len,sizeof(tarName));
status = -1;
}
else
{
status = uploadDebugoutput(outdir, tarName);
}
if(status != 0)
{
RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: RRD Upload Script Execution Failed!!! status:%d\n",__FUNCTION__,__LINE__,status);
Expand All @@ -588,14 +713,22 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf
}
free(rfcbuf); // free duplicated rfc data
free(buff->mdata); // free rfc data
buff->mdata = NULL;
free(buff->jsonPath); // free rrd path info
buff->jsonPath = NULL;
free(buff->suffix); // free suffix
buff->suffix = NULL;
}
else
{
RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: No Command excuted as RRD Failed to change directory:%s\n",__FUNCTION__,__LINE__,outdir);
free(rfcbuf); // free duplicated rfc data
free(buff->mdata); // free rfc data
buff->mdata = NULL;
free(buff->jsonPath); // free rrd path info
buff->jsonPath = NULL;
free(buff->suffix); // free suffix
buff->suffix = NULL;
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/rrdJsonParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ issueData* getIssueCommandInfo(issueNodeData *issuestructNode, cJSON *jsoncfg,ch
bool processAllDebugCommand(cJSON *jsoncfg, issueNodeData *issuestructNode, char *rfcbuf);
bool processAllDeepSleepAwkMetricsCommands(cJSON *jsoncfg, issueNodeData *issuestructNode, char *rfcbuf);

void split_issue_type(const char *input, char *base, size_t base_len, char *suffix, size_t suffix_len);

#ifdef __cplusplus
}
#endif
Expand Down
Loading
Loading