While running a static code analysis tool (Parfait) on fetchmail, it found some
bugs:
Error: Memory leak (CWE 401)
Memory leak of pointer 'plugin_copy' allocated with malloc((plugin_copy_len + 1))
at line 137 of components/fetchmail/fetchmail-6.3.22/socket.c in function 'parse_plugin'.
'plugin_copy' allocated at line 107 with malloc((plugin_copy_len + 1)).
plugin_copy leaks when plugin_copy_offset >= plugin_copy_len at line 114.
Error: Null pointer dereference (CWE 476)
Read from null pointer 'argvec'
at line 189 of components/fetchmail/fetchmail-6.3.22/socket.c in function 'handle_plugin'.
Function 'parse_plugin' may return constant 'NULL' at line 137, called at line 188.
Null pointer introduced at line 137 in function 'parse_plugin'.
at line 190 of components/fetchmail/fetchmail-6.3.22/socket.c in function 'handle_plugin'.
Function 'parse_plugin' may return constant 'NULL' at line 137, called at line 188.
Null pointer introduced at line 137 in function 'parse_plugin'.
(I realize these are on 6.3.22; I checked and verified that this portion of
the code is the same in 6.3.24.)
The attached patch fixes each of these.
(Note by Matthias Andree:
The NULL pointer dereference fix does not require error reporting,
because parse_plugin() will already have reported the out-of-memory
error that causes the NULL to be returned.)
argvec = (char **)malloc(s);
if (!argvec)
{
argvec = (char **)malloc(s);
if (!argvec)
{
report(stderr, GT_("fetchmail: malloc failed\n"));
return NULL;
}
report(stderr, GT_("fetchmail: malloc failed\n"));
return NULL;
}
if (outlevel >= O_VERBOSE)
report(stderr, GT_("running %s (host %s service %s)\n"), plugin, host, service);
argvec = parse_plugin(plugin,host,service);
if (outlevel >= O_VERBOSE)
report(stderr, GT_("running %s (host %s service %s)\n"), plugin, host, service);
argvec = parse_plugin(plugin,host,service);
+ if (argvec == NULL)
+ _exit(EXIT_FAILURE);
execvp(*argvec, argvec);
report(stderr, GT_("execvp(%s) failed\n"), *argvec);
_exit(EXIT_FAILURE);
execvp(*argvec, argvec);
report(stderr, GT_("execvp(%s) failed\n"), *argvec);
_exit(EXIT_FAILURE);