* [LTP] [PATCH] LTP/Lite test float_trigo core dumps due to free(): invalid pointer
@ 2026-07-08 9:37 Tomas Dzik via ltp
2026-07-08 10:21 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 3+ messages in thread
From: Tomas Dzik via ltp @ 2026-07-08 9:37 UTC (permalink / raw)
To: ltp
If malloc() fails and return value is not checked, the current code runs
free() on uninitialized pointer.
Here is the log from failed run:
~==== float_trigo ====
command: float_trigo -v
float_trigo 0 TINFO : Using /tmp/LTP_floJSug25 as tmpdir (xfs
filesystem)
float_trigo 1 TPASS : Test passed
float_trigo 0 TINFO : float_trigo: will run for 500 loops; using .
as a data directory
float_trigo 0 TINFO : float_trigo: will run 7 functions, 20
threads per function
float_trigo 0 TINFO : signal handler 140451533870784 started
float_trigo 0 TINFO : Signal handler starts waiting...
free(): invalid pointer
Duration: 0.926
This fix:
- initializes pointers where we actually core dumped (*din, *dex).
- adds checks for all malloc() return values int testcases/misc/math/float/
directory
- replaces sprintf() with more secure snprintf() variants
Signed-off-by: Tomas Dzik <tdzik@redhat.com>
---
testcases/misc/math/float/bessel/genbessel.c | 11 ++++---
.../misc/math/float/exp_log/genexp_log.c | 28 +++++++++-------
testcases/misc/math/float/iperb/geniperb.c | 9 +++--
testcases/misc/math/float/main.c | 17 +++++++---
testcases/misc/math/float/power/genpower.c | 16 +++++----
testcases/misc/math/float/thread_code.c | 33 +++++++++++++------
testcases/misc/math/float/trigo/gentrigo.c | 28 +++++++++-------
7 files changed, 89 insertions(+), 53 deletions(-)
diff --git a/testcases/misc/math/float/bessel/genbessel.c b/testcases/misc/math/float/bessel/genbessel.c
index 91ea3b6da..0954cfe0a 100644
--- a/testcases/misc/math/float/bessel/genbessel.c
+++ b/testcases/misc/math/float/bessel/genbessel.c
@@ -79,23 +79,24 @@ int main(int argc, char *argv[])
funct = malloc(strlen(bin_path) + MAX_FNAME_LEN);
if (funct == NULL)
err(1, "malloc failed");
- sprintf(funct, "%s/genj0", bin_path);
+
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genj0", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genj1", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genj1", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/geny0", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/geny0", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/geny1", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/geny1", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genlgamma", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genlgamma", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
diff --git a/testcases/misc/math/float/exp_log/genexp_log.c b/testcases/misc/math/float/exp_log/genexp_log.c
index 7f26945ec..dbab5cccd 100644
--- a/testcases/misc/math/float/exp_log/genexp_log.c
+++ b/testcases/misc/math/float/exp_log/genexp_log.c
@@ -25,11 +25,12 @@
/******************************************************************************/
#include <sys/types.h>
#include <sys/wait.h>
-#include <float.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
+#include <float.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
@@ -76,31 +77,34 @@ int main(int argc, char *argv[])
bin_path = argv[1];
funct = malloc(strlen(bin_path) + MAX_FNAME_LEN);
- sprintf(funct, "%s/genexp", bin_path);
+ if (funct == NULL)
+ err(1, "malloc failed");
+
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genexp", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genlog", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genlog", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genlog10", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genlog10", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genfrexp", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genfrexp", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genldexp", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genldexp", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genhypot", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genhypot", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genmodf", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genmodf", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
diff --git a/testcases/misc/math/float/iperb/geniperb.c b/testcases/misc/math/float/iperb/geniperb.c
index f7bf55c84..ec182a06b 100644
--- a/testcases/misc/math/float/iperb/geniperb.c
+++ b/testcases/misc/math/float/iperb/geniperb.c
@@ -78,15 +78,18 @@ int main(int argc, char *argv[])
bin_path = argv[1];
funct = malloc(strlen(bin_path) + MAX_FNAME_LEN);
- sprintf(funct, "%s/gencosh", bin_path);
+ if (funct == NULL)
+ err(1, "malloc failed");
+
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/gencosh", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/gensinh", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/gensinh", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/gentanh", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/gentanh", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
diff --git a/testcases/misc/math/float/main.c b/testcases/misc/math/float/main.c
index 7285141a4..53e59e241 100644
--- a/testcases/misc/math/float/main.c
+++ b/testcases/misc/math/float/main.c
@@ -83,11 +83,15 @@ int generate(char *datadir, char *bin_path)
{
char *cmdline;
char *fmt = "cd %s; %s/%s %s";
+ size_t cmdline_size;
- cmdline = malloc(2 * strlen(bin_path) + strlen(datadir) + strlen(GENERATOR) + strlen(fmt));
+ cmdline_size = 2 * strlen(bin_path) + strlen(datadir);
+ cmdline_size += strlen(GENERATOR) + strlen(fmt);
+
+ cmdline = malloc(cmdline_size);
if (cmdline == NULL)
return (1);
- sprintf(cmdline, fmt, datadir, bin_path, GENERATOR, bin_path);
+ snprintf(cmdline, cmdline_size, fmt, datadir, bin_path, GENERATOR, bin_path);
system(cmdline);
free(cmdline);
return (0);
@@ -114,6 +118,7 @@ int main(int argc, char *argv[])
int error = 0;
/*int time=1; */
int i;
+ size_t bin_path_size;
/* Generate test ID from invocation name */
if ((TCID = strrchr(argv[0], '/')) != NULL)
@@ -125,11 +130,13 @@ int main(int argc, char *argv[])
tst_brkm(TBROK, NULL,
"You must set $LTPROOT before executing this test");
}
- bin_path = malloc(strlen(ltproot) + 16);
+
+ bin_path_size = strlen(ltproot) + 16;
+ bin_path = malloc(bin_path_size);
if (bin_path == NULL) {
tst_brkm(TBROK | TERRNO, NULL, "malloc failed");
}
- sprintf(bin_path, "%s/testcases/bin", ltproot);
+ snprintf(bin_path, bin_path_size, "%s/testcases/bin", ltproot);
tst_tmpdir();
@@ -432,6 +439,6 @@ static void sys_error(const char *msg, int line)
{
char syserr_msg[256];
- sprintf(syserr_msg, "%s: %s", msg, strerror(errno));
+ snprintf(syserr_msg, sizeof(syserr_msg), "%s: %s", msg, strerror(errno));
error(syserr_msg, line);
}
diff --git a/testcases/misc/math/float/power/genpower.c b/testcases/misc/math/float/power/genpower.c
index 44f7af934..b2c1171c0 100644
--- a/testcases/misc/math/float/power/genpower.c
+++ b/testcases/misc/math/float/power/genpower.c
@@ -34,6 +34,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <err.h>
#include <sys/signal.h>
#include <math.h>
@@ -76,27 +77,30 @@ int main(int argc, char *argv[])
bin_path = argv[1];
funct = malloc(strlen(bin_path) + MAX_FNAME_LEN);
- sprintf(funct, "%s/genceil", bin_path);
+ if (funct == NULL)
+ err(1, "malloc failed");
+
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genceil", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genfabs", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genfabs", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genfloor", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genfloor", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genfmod", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genfmod", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genpow", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genpow", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/gensqrt", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/gensqrt", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
diff --git a/testcases/misc/math/float/thread_code.c b/testcases/misc/math/float/thread_code.c
index ca18cef1e..b67edbb34 100644
--- a/testcases/misc/math/float/thread_code.c
+++ b/testcases/misc/math/float/thread_code.c
@@ -47,7 +47,7 @@ static size_t read_file(char *fname, void **data)
int fd;
int maxretries = 1;
- (void)sprintf(path, "%s/%s", datadir, fname);
+ (void)snprintf(path, PATH_MAX, "%s/%s", datadir, fname);
errno = 0;
@@ -135,7 +135,8 @@ static void check_error(TH_DATA * th_data, double e, double r, int index)
++th_data->th_nerror;
/* record first error only ! */
if (th_data->th_result == 0) {
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
errtmplt,
th_data->th_func.fident,
index, e, r, x);
@@ -194,7 +195,8 @@ static void compute_modf(TH_DATA * th_data, double *din, double *dex,
++th_data->th_nerror;
/* record first error only ! */
if (th_data->th_result == 0) {
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
errtmplt1,
th_data->th_func.fident,
index, dex2[index], tmp);
@@ -239,7 +241,8 @@ static void compute_frexp_lgamma(TH_DATA * th_data, double *din, double *dex,
++th_data->th_nerror;
/* record first error only ! */
if (th_data->th_result == 0) {
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
errtmplt2,
th_data->th_func.fident,
index, dex2[index], tmp);
@@ -278,12 +281,18 @@ void *thread_code(void *arg)
{
TH_DATA *th_data = (TH_DATA *) arg;
size_t fsize, fsize2, fsize3;
- double *din, *dex, *dex2 = NULL;
+ /*
+ * If read_file() fails for whatever reason, these pointers might
+ * stay uninitialized. Initialize them to NULL, because SAFE_FREE()
+ * can handle it.
+ */
+ double *din = NULL, *dex = NULL, *dex2 = NULL;
int imax, index;
fsize = read_file(th_data->th_func.din_fname, (void **)&din);
if (fsize == (size_t) 0) {
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
"FAIL: %s: reading %s, %s\n",
th_data->th_func.fident,
th_data->th_func.din_fname, strerror(errno));
@@ -293,7 +302,8 @@ void *thread_code(void *arg)
}
fsize2 = read_file(th_data->th_func.dex_fname, (void **)&dex);
if (fsize2 == (size_t) 0) {
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
"FAIL: %s: reading %s, %s\n",
th_data->th_func.fident,
th_data->th_func.dex_fname, strerror(errno));
@@ -313,7 +323,8 @@ void *thread_code(void *arg)
case FUNC_GAM:
fsize3 = read_file(th_data->th_func.dex2_fname, (void **)&dex2);
if (fsize3 == (size_t) 0) {
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
"FAIL: %s: reading %s, %s\n",
th_data->th_func.fident,
th_data->th_func.dex2_fname, strerror(errno));
@@ -346,7 +357,8 @@ void *thread_code(void *arg)
break;
default:
file_size_error:
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
"FAIL: %s: file sizes don't match\n",
th_data->th_func.fident);
th_data->th_result = 1;
@@ -390,7 +402,8 @@ file_size_error:
din, dex, (int *)dex2, index);
break;
default:
- sprintf(th_data->detail_data,
+ snprintf(th_data->detail_data,
+ DETAIL_DATA_SIZE,
"FAIL: %s: unexpected function type\n",
th_data->th_func.fident);
th_data->th_result = 1;
diff --git a/testcases/misc/math/float/trigo/gentrigo.c b/testcases/misc/math/float/trigo/gentrigo.c
index 5f7e0cbc7..0d512d17f 100644
--- a/testcases/misc/math/float/trigo/gentrigo.c
+++ b/testcases/misc/math/float/trigo/gentrigo.c
@@ -25,11 +25,12 @@
/******************************************************************************/
#include <sys/types.h>
#include <sys/wait.h>
-#include <float.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
+#include <float.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
@@ -77,31 +78,34 @@ int main(int argc, char *argv[])
bin_path = argv[1];
funct = malloc(strlen(bin_path) + MAX_FNAME_LEN);
- sprintf(funct, "%s/gencos", bin_path);
+ if (funct == NULL)
+ err(1, "malloc failed");
+
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/gencos", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/gensin", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/gensin", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/gentan", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/gentan", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genatan", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genatan", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genatan2", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genatan2", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genacos", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genacos", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
- sprintf(funct, "%s/genasin", bin_path);
+ snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN, "%s/genasin", bin_path);
child = create_file(funct, 0);
waitpid(child, NULL, 0);
--
2.55.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [LTP] LTP/Lite test float_trigo core dumps due to free(): invalid pointer
2026-07-08 9:37 [LTP] [PATCH] LTP/Lite test float_trigo core dumps due to free(): invalid pointer Tomas Dzik via ltp
@ 2026-07-08 10:21 ` linuxtestproject.agent
0 siblings, 0 replies; 3+ messages in thread
From: linuxtestproject.agent @ 2026-07-08 10:21 UTC (permalink / raw)
To: Tomas Dzik; +Cc: ltp
Hi Tomas,
On Wed, 08 Jul 2026 11:37:15 +0200, Tomas Dzik wrote:
> LTP/Lite test float_trigo core dumps due to free(): invalid pointer
> This fix:
> - initializes pointers where we actually core dumped (*din, *dex).
> - adds checks for all malloc() return values int testcases/misc/math/float/
> directory
> - replaces sprintf() with more secure snprintf() variants
Typo: "int" should be "in".
The commit message lists three distinct changes: initializing the din/dex
pointers in thread_code.c (the crash fix), adding malloc() NULL checks
in the gen*.c files, and replacing sprintf() with snprintf() across 7
files.
These are independently reviewable and deployable changes. The crash fix
is self-contained in thread_code.c. The malloc checks and the
sprintf->snprintf replacements can be bisected and reverted separately.
Please split into separate patches.
Splitting would also let each patch carry a precise subject. The current
subject names float_trigo, but the changes span bessel/, exp_log/,
iperb/, power/, trigo/, thread_code.c, and main.c.
Verdict - Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [LTP] LTP/Lite test float_trigo core dumps due to free(): invalid pointer
2026-07-09 15:40 [LTP] [PATCH 1/3] " Tomas Dzik via ltp
@ 2026-07-09 16:34 ` linuxtestproject.agent
0 siblings, 0 replies; 3+ messages in thread
From: linuxtestproject.agent @ 2026-07-09 16:34 UTC (permalink / raw)
To: Tomas Dzik; +Cc: ltp
Hi Tomas,
On Thu, 09 Jul 2026 17:40:04 +0200, Tomas Dzik wrote:
> LTP/Lite test float_trigo core dumps due to free(): invalid pointer
--- [PATCH 1/3] ---
> If malloc() inside function read_file() fails and return value is
> not checked, the current code runs free() on uninitialized pointer.
The return value of read_file() is checked by thread_code() via
`if (fsize == (size_t) 0)`. Is the description perhaps trying to say
that read_file() does not initialize *data on failure paths, so the
caller ends up calling SAFE_FREE() on an uninitialized pointer?
The fix itself is correct -- initializing din and dex to NULL ensures
SAFE_FREE() is a no-op on the error path.
--- [PATCH 3/3] ---
> - sprintf(funct, "%s/gensinh", bin_path);
> + snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN,
> + "%s/gensinh", bin_path);
> child = create_file(funct, 0);
> waitpid(child, NULL, 0);
>
> sprintf(funct, "%s/gentanh", bin_path);
> + snprintf(funct, strlen(bin_path) + MAX_FNAME_LEN,
> + "%s/gentanh", bin_path);
The sprintf() line for "gentanh" in geniperb.c was not removed. Both
calls are present in the result: the old sprintf() writes the path,
then the new snprintf() overwrites it with the same value, and
create_file() runs once. Functionally identical, but the unreplaced
sprintf() is the exact call this patch is meant to eliminate.
Verdict - Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-09 16:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 9:37 [LTP] [PATCH] LTP/Lite test float_trigo core dumps due to free(): invalid pointer Tomas Dzik via ltp
2026-07-08 10:21 ` [LTP] " linuxtestproject.agent
-- strict thread matches above, loose matches on Subject: below --
2026-07-09 15:40 [LTP] [PATCH 1/3] " Tomas Dzik via ltp
2026-07-09 16:34 ` [LTP] " linuxtestproject.agent
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox