From 2155a24b846ee370f05572254fb4fd7d5166a24b Mon Sep 17 00:00:00 2001 From: Emma Stensland Date: Wed, 27 May 2026 15:41:05 -0600 Subject: [PATCH] F-1118 fixed memory leak in realloc --- .gitignore | 9 +++++ src/tools/clu_funcs.c | 68 ++++++++++++++++++++++++++---------- src/x509/clu_config.c | 43 +++++++++++++---------- src/x509/clu_request_setup.c | 6 ++-- wolfclu/clu_header_main.h | 6 +++- 5 files changed, 92 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index 21418665..ba9c8551 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,12 @@ x64/ .vs/ __pycache__/ CLAUDE.md + +# x509 test runtime artifacts (generated in cwd by tests/x509/*.py) +/ca_*.conf +/test_req_rt.conf +/test_x509req_*.conf +/*.csr +/index.txt +/serial-file-test +/rand-file-test diff --git a/src/tools/clu_funcs.c b/src/tools/clu_funcs.c index 2b391c60..d0521567 100644 --- a/src/tools/clu_funcs.c +++ b/src/tools/clu_funcs.c @@ -1349,46 +1349,55 @@ WOLFSSL_X509_NAME* wolfCLU_ParseX509NameString(const char* n, int nSz) return ret; } -size_t wolfCLU_getline(char **lineptr, size_t *len, FILE *fp) +int wolfCLU_getline(char **lineptr, size_t *len, FILE *fp) { - - char line[MAX_ENTRY_NAME]; + char line[MAX_ENTRY_NAME]; + char *tmp; *len = sizeof(line); - *lineptr = NULL; + if ((*lineptr = (char*)XMALLOC(*len, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER)) == NULL) { - XFREE(*lineptr, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return 0; + *len = 0; + return WOLFCLU_FATAL_ERROR; } - (*lineptr)[0] = '\0'; - while(fgets(line, sizeof(line), fp) != NULL) { - size_t len_used = XSTRLEN(*lineptr); + while (fgets(line, sizeof(line), fp) != NULL) { + size_t len_used = XSTRLEN(*lineptr); size_t line_used = XSTRLEN(line); - if(*len - len_used < line_used) { + if (*len - len_used <= line_used) { + if (*len > (size_t)(INT_MAX / 2)) { + XFREE(*lineptr, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + *lineptr = NULL; + *len = 0; + return WOLFCLU_FATAL_ERROR; + } *len *= 2; - - if((*lineptr = XREALLOC(*lineptr, *len, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER)) == NULL) { - return -1; + tmp = XREALLOC(*lineptr, *len, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + XFREE(*lineptr, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + *lineptr = NULL; + *len = 0; + return WOLFCLU_FATAL_ERROR; } + *lineptr = tmp; } XMEMCPY(*lineptr + len_used, line, line_used); len_used += line_used; (*lineptr)[len_used] = '\0'; - if((*lineptr)[len_used - 1] == '\n') { - (*lineptr)[len_used - 1]='\0'; - return len_used; + if (len_used > 0 && (*lineptr)[len_used - 1] == '\n') { + (*lineptr)[len_used - 1] = '\0'; + return (int)(len_used - 1); } } - return -1; + /* EOF without newline: return accumulated length (0 if nothing was read) */ + return (int)XSTRLEN(*lineptr); } /* returns WOLFCLU_SUCCESS on success */ @@ -1396,7 +1405,7 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) { char *in = NULL; size_t inSz; - size_t ret; + int ret; FILE *fout = stdout; FILE *fin = stdin; /* defaulting to stdin but using a fd variable to make it * easy for expanding to other inputs */ @@ -1405,6 +1414,9 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) "skipped.\nExamples of inputs are provided as [*]\n"); fprintf(fout, "Country [US] : "); ret = wolfCLU_getline(&in, &inSz, fin); + if (ret == WOLFCLU_FATAL_ERROR) { + return WOLFCLU_FATAL_ERROR; + } if (ret > 0) { wolfCLU_AddNameEntry(name, CTC_PRINTABLE, NID_countryName, in); } @@ -1412,6 +1424,9 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) fprintf(fout, "State or Province [Montana] : "); ret = wolfCLU_getline(&in, &inSz, fin); + if (ret == WOLFCLU_FATAL_ERROR) { + return WOLFCLU_FATAL_ERROR; + } if (ret > 0) { wolfCLU_AddNameEntry(name, CTC_UTF8, NID_stateOrProvinceName, in); } @@ -1419,6 +1434,9 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) fprintf(fout, "Locality [Bozeman] : "); ret = wolfCLU_getline(&in, &inSz, fin); + if (ret == WOLFCLU_FATAL_ERROR) { + return WOLFCLU_FATAL_ERROR; + } if (ret > 0) { wolfCLU_AddNameEntry(name, CTC_UTF8, NID_localityName, in); } @@ -1426,6 +1444,9 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) fprintf(fout, "Organization Name [wolfSSL] : "); ret = wolfCLU_getline(&in, &inSz, fin); + if (ret == WOLFCLU_FATAL_ERROR) { + return WOLFCLU_FATAL_ERROR; + } if (ret > 0) { wolfCLU_AddNameEntry(name, CTC_UTF8, NID_organizationName, in); } @@ -1433,6 +1454,9 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) fprintf(fout, "Organization Unit [engineering] : "); ret = wolfCLU_getline(&in, &inSz, fin); + if (ret == WOLFCLU_FATAL_ERROR) { + return WOLFCLU_FATAL_ERROR; + } if (ret > 0) { wolfCLU_AddNameEntry(name, CTC_UTF8, NID_organizationalUnitName, in); } @@ -1440,6 +1464,9 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) fprintf(fout, "Common Name : "); ret = wolfCLU_getline(&in, &inSz, fin); + if (ret == WOLFCLU_FATAL_ERROR) { + return WOLFCLU_FATAL_ERROR; + } if (ret > 0) { wolfCLU_AddNameEntry(name, CTC_UTF8, NID_commonName, in); } @@ -1447,6 +1474,9 @@ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* name) fprintf(fout, "Email Address : "); ret = wolfCLU_getline(&in, &inSz, fin); + if (ret == WOLFCLU_FATAL_ERROR) { + return WOLFCLU_FATAL_ERROR; + } if (ret > 0) { wolfCLU_AddNameEntry(name, CTC_UTF8, NID_emailAddress, in); } diff --git a/src/x509/clu_config.c b/src/x509/clu_config.c index 03051aa2..3be76137 100644 --- a/src/x509/clu_config.c +++ b/src/x509/clu_config.c @@ -549,6 +549,7 @@ static int CheckDisName(WOLFSSL_CONF* conf, char* sect, WOLFSSL_X509_NAME* name, char* deflt = NULL; char *in = NULL; size_t inSz; + int lineRet; char* deflt_str = NULL; char* mn_str = NULL; @@ -602,30 +603,36 @@ static int CheckDisName(WOLFSSL_CONF* conf, char* sect, WOLFSSL_X509_NAME* name, deflt = wolfSSL_NCONF_get_string(conf, sect, deflt_str); fprintf(fout, "%s [%s] : ", curnt, (deflt)?deflt:""); - if (wolfCLU_getline(&in, &inSz, fin) > 1) { - deflt = in; + lineRet = wolfCLU_getline(&in, &inSz, fin); + if (lineRet == WOLFCLU_FATAL_ERROR) { + ret = WOLFCLU_FATAL_ERROR; } - - if (deflt && XSTRCMP(deflt, ".") != 0) { - if (wolfSSL_NCONF_get_number(conf, sect, mx_str, &mx) == - WOLFSSL_SUCCESS && (long)XSTRLEN(deflt) > mx) { - WOLFCLU_LOG(WOLFCLU_E0, - "Name %s is larger than max %ld", deflt, mx); - ret = WOLFCLU_FATAL_ERROR; + else { + if (lineRet > 0) { + deflt = in; } - if (wolfSSL_NCONF_get_number(conf, sect, mn_str, &mn) == - WOLFSSL_SUCCESS && (long)XSTRLEN(deflt) < mn) { - WOLFCLU_LOG(WOLFCLU_E0, - "Name %s is smaller than min %ld", deflt, mn); - ret = WOLFCLU_FATAL_ERROR; - } + if (deflt && XSTRCMP(deflt, ".") != 0) { + if (wolfSSL_NCONF_get_number(conf, sect, mx_str, &mx) == + WOLFSSL_SUCCESS && (long)XSTRLEN(deflt) > mx) { + WOLFCLU_LOG(WOLFCLU_E0, + "Name %s is larger than max %ld", deflt, mx); + ret = WOLFCLU_FATAL_ERROR; + } + + if (wolfSSL_NCONF_get_number(conf, sect, mn_str, &mn) == + WOLFSSL_SUCCESS && (long)XSTRLEN(deflt) < mn) { + WOLFCLU_LOG(WOLFCLU_E0, + "Name %s is smaller than min %ld", deflt, mn); + ret = WOLFCLU_FATAL_ERROR; + } - if (ret == WOLFCLU_SUCCESS) { - wolfCLU_AddNameEntry(name, strType, nid, deflt); + if (ret == WOLFCLU_SUCCESS) { + wolfCLU_AddNameEntry(name, strType, nid, deflt); + } } } - free(in); in = NULL; + XFREE(in, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); in = NULL; } } diff --git a/src/x509/clu_request_setup.c b/src/x509/clu_request_setup.c index 89b003e1..80494618 100644 --- a/src/x509/clu_request_setup.c +++ b/src/x509/clu_request_setup.c @@ -880,8 +880,10 @@ int wolfCLU_requestSetup(int argc, char** argv) ret = MEMORY_E; } else { - wolfCLU_CreateX509Name(name); - wolfSSL_X509_REQ_set_subject_name(x509, name); + ret = wolfCLU_CreateX509Name(name); + if (ret == WOLFCLU_SUCCESS) { + wolfSSL_X509_REQ_set_subject_name(x509, name); + } wolfSSL_X509_NAME_free(name); } } diff --git a/wolfclu/clu_header_main.h b/wolfclu/clu_header_main.h index 3f10d1ce..7f239b97 100644 --- a/wolfclu/clu_header_main.h +++ b/wolfclu/clu_header_main.h @@ -455,8 +455,11 @@ int wolfCLU_GetOpt(int argc, char** argv, const char *options, const struct opti /** * @brief wolfCLU getline() implementation + * + * @return length of the line read (>= 0) on success, or WOLFCLU_FATAL_ERROR + * if a buffer allocation fails */ -size_t wolfCLU_getline(char **line, size_t *len, FILE *fp); +int wolfCLU_getline(char **line, size_t *len, FILE *fp); /* * generic function to check for a specific input argument. Return the @@ -506,6 +509,7 @@ WOLFSSL_X509_NAME* wolfCLU_ParseX509NameString(const char* n, int nSz); * * @param x509 the name structure to be filled in * @return WOLFCLU_SUCCESS On successfully setting the name + * @return WOLFCLU_FATAL_ERROR if reading an input field fails to allocate */ int wolfCLU_CreateX509Name(WOLFSSL_X509_NAME* x509);