The calls to malloc()
fail to check whether a null pointer was returned by using it. This gives undefined behaviour.
The calculation is wrong here, where fbRange
is an array of pointers, not an array of `char[FBSIZE]:
size_t arraySize = length * FBSIZE;
char** fbRange = malloc(arraySize);
To ensure that the calculation is correct, it's usual to ask the compiler for the right size:
char** fbRange = malloc(sizeof *fbRange * length);
On the good side, Valgrind does confirm that the code correctly frees everything it allocates.
There's no checking that the command-line arguments are actually convertible to integers:
int from = strtol(argv[1], NULL, 10);
int to = strtol(argv[2], NULL, 10);
We need to pass an actual end-pointer as second argument, and check that it points to a null character after the conversion (and that we didn't pass an empty string).
Compiling with full analysis reveals some aspects that can easily be improved (some mentioned above; some not):
gcc-11 -std=c17 -fPIC -gdwarf-4 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds -Wconversion -fanalyzer -Wstrict-prototypes 268859.c -o 268859
268859.c: In function ‘fizzBuzzRange’:
268859.c:30:21: warning: conversion to ‘size_t’ {aka ‘long unsigned int’} from ‘int’ may change the sign of the result [-Wsign-conversion]
30 | size_t length = to - from + 1;
| ^~
268859.c:34:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
34 | for (int index = 0; index < length; index++) {
| ^
268859.c: In function ‘main’:
268859.c:48:16: warning: conversion from ‘long int’ to ‘int’ may change value [-Wconversion]
48 | int from = strtol(argv[1], NULL, 10);
| ^~~~~~
268859.c:49:14: warning: conversion from ‘long int’ to ‘int’ may change value [-Wconversion]
49 | int to = strtol(argv[2], NULL, 10);
| ^~~~~~
268859.c: In function ‘numToFizzBuzz’:
268859.c:15:9: warning: use of possibly-NULL ‘fizzBuzz’ where non-null expected [CWE-690] [-Wanalyzer-possible-null-argument]
15 | strcpy(fizzBuzz, "FizzBuzz");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
‘main’: events 1-6
|
| 42 | int main(int argc, char** argv) {
| | ^~~~
| | |
| | (1) entry to ‘main’
| 43 | if (argc < 3) {
| | ~
| | |
| | (2) following ‘false’ branch (when ‘argc > 2’)...
|......
| 48 | int from = strtol(argv[1], NULL, 10);
| | ~
| | |
| | (3) ...to here
| 49 | int to = strtol(argv[2], NULL, 10);
| 50 | if (from > to) {
| | ~
| | |
| | (4) following ‘false’ branch (when ‘from <= to’)...
|......
| 55 | char** fbRange = fizzBuzzRange(from, to);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| | (6) calling ‘fizzBuzzRange’ from ‘main’
|
+--> ‘fizzBuzzRange’: events 7-10
|
| 29 | char** fizzBuzzRange(int from, int to) {
| | ^~~~~~~~~~~~~
| | |
| | (7) entry to ‘fizzBuzzRange’
|......
| 34 | for (int index = 0; index < length; index++) {
| | ~~~~~~~~~~~~~~
| | |
| | (8) following ‘true’ branch...
| 35 | fbRange[index] = numToFizzBuzz(index + from);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (9) ...to here
| | (10) calling ‘numToFizzBuzz’ from ‘fizzBuzzRange’
|
+--> ‘numToFizzBuzz’: events 11-15
|
| 9 | char* numToFizzBuzz(int num) {
| | ^~~~~~~~~~~~~
| | |
| | (11) entry to ‘numToFizzBuzz’
| 10 | char* fizzBuzz = malloc(FBSIZE);
| | ~~~~~~~~~~~~~~
| | |
| | (12) this call could return NULL
|......
| 14 | if (isDivBy3 && isDivBy5) {
| | ~
| | |
| | (13) following ‘true’ branch...
| 15 | strcpy(fizzBuzz, "FizzBuzz");
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (14) ...to here
| | (15) argument 1 (‘fizzBuzz’) from (12) could be NULL where non-null expected
|
<built-in>: note: argument 1 of ‘__builtin_memcpy’ must be non-null
268859.c:17:9: warning: use of possibly-NULL ‘fizzBuzz’ where non-null expected [CWE-690] [-Wanalyzer-possible-null-argument]
17 | strcpy(fizzBuzz, "Fizz");
| ^~~~~~~~~~~~~~~~~~~~~~~~
‘main’: events 1-6
|
| 42 | int main(int argc, char** argv) {
| | ^~~~
| | |
| | (1) entry to ‘main’
| 43 | if (argc < 3) {
| | ~
| | |
| | (2) following ‘false’ branch (when ‘argc > 2’)...
|......
| 48 | int from = strtol(argv[1], NULL, 10);
| | ~
| | |
| | (3) ...to here
| 49 | int to = strtol(argv[2], NULL, 10);
| 50 | if (from > to) {
| | ~
| | |
| | (4) following ‘false’ branch (when ‘from <= to’)...
|......
| 55 | char** fbRange = fizzBuzzRange(from, to);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| | (6) calling ‘fizzBuzzRange’ from ‘main’
|
+--> ‘fizzBuzzRange’: events 7-10
|
| 29 | char** fizzBuzzRange(int from, int to) {
| | ^~~~~~~~~~~~~
| | |
| | (7) entry to ‘fizzBuzzRange’
|......
| 34 | for (int index = 0; index < length; index++) {
| | ~~~~~~~~~~~~~~
| | |
| | (8) following ‘true’ branch...
| 35 | fbRange[index] = numToFizzBuzz(index + from);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (9) ...to here
| | (10) calling ‘numToFizzBuzz’ from ‘fizzBuzzRange’
|
+--> ‘numToFizzBuzz’: events 11-17
|
| 9 | char* numToFizzBuzz(int num) {
| | ^~~~~~~~~~~~~
| | |
| | (11) entry to ‘numToFizzBuzz’
| 10 | char* fizzBuzz = malloc(FBSIZE);
| | ~~~~~~~~~~~~~~
| | |
| | (12) this call could return NULL
|......
| 14 | if (isDivBy3 && isDivBy5) {
| | ~~~~~~~~~~~~~~~~~~~~
| | |
| | (13) following ‘false’ branch (when ‘isDivBy5 == 0’)...
| 15 | strcpy(fizzBuzz, "FizzBuzz");
| 16 | } else if (isDivBy3) {
| | ~
| | |
| | (14) ...to here
| | (15) following ‘true’ branch (when ‘isDivBy3 != 0’)...
| 17 | strcpy(fizzBuzz, "Fizz");
| | ~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (16) ...to here
| | (17) argument 1 (‘fizzBuzz’) from (12) could be NULL where non-null expected
|
<built-in>: note: argument 1 of ‘__builtin_memcpy’ must be non-null
268859.c:19:9: warning: use of possibly-NULL ‘fizzBuzz’ where non-null expected [CWE-690] [-Wanalyzer-possible-null-argument]
19 | strcpy(fizzBuzz, "Buzz");
| ^~~~~~~~~~~~~~~~~~~~~~~~
‘main’: events 1-6
|
| 42 | int main(int argc, char** argv) {
| | ^~~~
| | |
| | (1) entry to ‘main’
| 43 | if (argc < 3) {
| | ~
| | |
| | (2) following ‘false’ branch (when ‘argc > 2’)...
|......
| 48 | int from = strtol(argv[1], NULL, 10);
| | ~
| | |
| | (3) ...to here
| 49 | int to = strtol(argv[2], NULL, 10);
| 50 | if (from > to) {
| | ~
| | |
| | (4) following ‘false’ branch (when ‘from <= to’)...
|......
| 55 | char** fbRange = fizzBuzzRange(from, to);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| | (6) calling ‘fizzBuzzRange’ from ‘main’
|
+--> ‘fizzBuzzRange’: events 7-10
|
| 29 | char** fizzBuzzRange(int from, int to) {
| | ^~~~~~~~~~~~~
| | |
| | (7) entry to ‘fizzBuzzRange’
|......
| 34 | for (int index = 0; index < length; index++) {
| | ~~~~~~~~~~~~~~
| | |
| | (8) following ‘true’ branch...
| 35 | fbRange[index] = numToFizzBuzz(index + from);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (9) ...to here
| | (10) calling ‘numToFizzBuzz’ from ‘fizzBuzzRange’
|
+--> ‘numToFizzBuzz’: events 11-17
|
| 9 | char* numToFizzBuzz(int num) {
| | ^~~~~~~~~~~~~
| | |
| | (11) entry to ‘numToFizzBuzz’
| 10 | char* fizzBuzz = malloc(FBSIZE);
| | ~~~~~~~~~~~~~~
| | |
| | (12) this call could return NULL
|......
| 16 | } else if (isDivBy3) {
| | ~
| | |
| | (13) following ‘false’ branch (when ‘isDivBy3 == 0’)...
| 17 | strcpy(fizzBuzz, "Fizz");
| 18 | } else if (isDivBy5) {
| | ~
| | |
| | (14) ...to here
| | (15) following ‘true’ branch (when ‘isDivBy5 != 0’)...
| 19 | strcpy(fizzBuzz, "Buzz");
| | ~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (16) ...to here
| | (17) argument 1 (‘fizzBuzz’) from (12) could be NULL where non-null expected
|
<built-in>: note: argument 1 of ‘__builtin_memcpy’ must be non-null
268859.c:21:9: warning: use of possibly-NULL ‘fizzBuzz’ where non-null expected [CWE-690] [-Wanalyzer-possible-null-argument]
21 | sprintf(fizzBuzz, "%d", num);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
‘main’: events 1-6
|
| 42 | int main(int argc, char** argv) {
| | ^~~~
| | |
| | (1) entry to ‘main’
| 43 | if (argc < 3) {
| | ~
| | |
| | (2) following ‘false’ branch (when ‘argc > 2’)...
|......
| 48 | int from = strtol(argv[1], NULL, 10);
| | ~
| | |
| | (3) ...to here
| 49 | int to = strtol(argv[2], NULL, 10);
| 50 | if (from > to) {
| | ~
| | |
| | (4) following ‘false’ branch (when ‘from <= to’)...
|......
| 55 | char** fbRange = fizzBuzzRange(from, to);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| | (6) calling ‘fizzBuzzRange’ from ‘main’
|
+--> ‘fizzBuzzRange’: events 7-10
|
| 29 | char** fizzBuzzRange(int from, int to) {
| | ^~~~~~~~~~~~~
| | |
| | (7) entry to ‘fizzBuzzRange’
|......
| 34 | for (int index = 0; index < length; index++) {
| | ~~~~~~~~~~~~~~
| | |
| | (8) following ‘true’ branch...
| 35 | fbRange[index] = numToFizzBuzz(index + from);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (9) ...to here
| | (10) calling ‘numToFizzBuzz’ from ‘fizzBuzzRange’
|
+--> ‘numToFizzBuzz’: events 11-17
|
| 9 | char* numToFizzBuzz(int num) {
| | ^~~~~~~~~~~~~
| | |
| | (11) entry to ‘numToFizzBuzz’
| 10 | char* fizzBuzz = malloc(FBSIZE);
| | ~~~~~~~~~~~~~~
| | |
| | (12) this call could return NULL
|......
| 16 | } else if (isDivBy3) {
| | ~
| | |
| | (13) following ‘false’ branch (when ‘isDivBy3 == 0’)...
| 17 | strcpy(fizzBuzz, "Fizz");
| 18 | } else if (isDivBy5) {
| | ~
| | |
| | (14) ...to here
| | (15) following ‘false’ branch (when ‘isDivBy5 == 0’)...
|......
| 21 | sprintf(fizzBuzz, "%d", num);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (16) ...to here
| | (17) argument 1 (‘fizzBuzz’) from (12) could be NULL where non-null expected
|
In file included from 268859.c:4:
/usr/include/stdio.h:334:12: note: argument 1 of ‘sprintf’ must be non-null
334 | extern int sprintf (char *__restrict __s,
| ^~~~~~~
268859.c: In function ‘fizzBuzzRange’:
268859.c:35:24: warning: dereference of possibly-NULL ‘fbRange’ [CWE-690] [-Wanalyzer-possible-null-dereference]
35 | fbRange[index] = numToFizzBuzz(index + from);
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
‘main’: events 1-6
|
| 42 | int main(int argc, char** argv) {
| | ^~~~
| | |
| | (1) entry to ‘main’
| 43 | if (argc < 3) {
| | ~
| | |
| | (2) following ‘false’ branch (when ‘argc > 2’)...
|......
| 48 | int from = strtol(argv[1], NULL, 10);
| | ~
| | |
| | (3) ...to here
| 49 | int to = strtol(argv[2], NULL, 10);
| 50 | if (from > to) {
| | ~
| | |
| | (4) following ‘false’ branch (when ‘from <= to’)...
|......
| 55 | char** fbRange = fizzBuzzRange(from, to);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (5) ...to here
| | (6) calling ‘fizzBuzzRange’ from ‘main’
|
+--> ‘fizzBuzzRange’: events 7-11
|
| 29 | char** fizzBuzzRange(int from, int to) {
| | ^~~~~~~~~~~~~
| | |
| | (7) entry to ‘fizzBuzzRange’
|......
| 32 | char** fbRange = malloc(arraySize);
| | ~~~~~~~~~~~~~~~~~
| | |
| | (8) this call could return NULL
| 33 |
| 34 | for (int index = 0; index < length; index++) {
| | ~~~~~~~~~~~~~~
| | |
| | (9) following ‘true’ branch...
| 35 | fbRange[index] = numToFizzBuzz(index + from);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
| | | (10) ...to here
| | (11) ‘fbRange + (long unsigned int)index * 8’ could be NULL: unchecked value from (8)
|