Skip to content

Commit

Permalink
Avoid using atoi() to parse integers
Browse files Browse the repository at this point in the history
Use a validating function instead.
  • Loading branch information
DemiMarie committed Jan 8, 2025
1 parent ef362e4 commit 856316d
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 19 deletions.
17 changes: 0 additions & 17 deletions daemon/qrexec-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,6 @@ _Noreturn static void usage(const char *const name, int status)
exit(status);
}

static int parse_int(const char *str, const char *msg) {
long value;
char *end = (char *)str;

if (str[0] < '0' || str[0] > '9')
errx(1, "%s '%s' does not start with an ASCII digit", msg, str);
errno = 0;
value = strtol(str, &end, 0);
if (*end != '\0')
errx(1, "trailing junk '%s' after %s", end, msg);
if (errno == 0 && (value < 0 || value > INT_MAX))
errno = ERANGE;
if (errno)
err(1, "invalid %s '%s': strtol", msg, str);
return (int)value;
}

static void parse_connect(char *str, char **request_id,
char **src_domain_name, int *src_domain_id)
{
Expand Down
19 changes: 19 additions & 0 deletions daemon/qrexec-daemon-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <limits.h>

#include "qrexec.h"
#include "libqrexec-utils.h"
Expand All @@ -14,6 +16,23 @@ const char *socket_dir = QREXEC_DAEMON_SOCKET_DIR;
#define QREXEC_DISPVM_PREFIX "@dispvm:"
#define QREXEC_DISPVM_PREFIX_SIZE (sizeof QREXEC_DISPVM_PREFIX - 1)

int parse_int(const char *str, const char *msg) {
long value;
char *end = (char *)str;

if (str[0] < '0' || str[0] > '9')
errx(1, "%s '%s' does not start with an ASCII digit", msg, str);
errno = 0;
value = strtol(str, &end, 0);
if (*end != '\0')
errx(1, "trailing junk '%s' after %s", end, msg);
if (errno == 0 && (value < 0 || value > INT_MAX))
errno = ERANGE;
if (errno)
err(1, "invalid %s '%s': strtol", msg, str);
return (int)value;
}

/* ask the daemon to allocate vchan port */
bool negotiate_connection_params(int s, int other_domid, unsigned type,
const void *cmdline_param, int cmdline_size,
Expand Down
9 changes: 9 additions & 0 deletions daemon/qrexec-daemon-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,12 @@ bool qrexec_execute_vm(const char *target, bool autostart, int remote_domain_id,
extern int local_stdin_fd;
__attribute__((warn_unused_result))
bool target_refers_to_dom0(const char *target);
/**
* Parse an integer, which must not be negative.
*
* @param str The integer.
* @param message A human-readable string that will be used in error messages.
*
* Returns a non-negative int on success. Calls exit(1) on failure.
*/
int parse_int(const char *str, const char *msg);
4 changes: 2 additions & 2 deletions daemon/qrexec-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ static void init(int xid, bool opt_direct)
}
startup_timeout_str = getenv("QREXEC_STARTUP_TIMEOUT");
if (startup_timeout_str) {
startup_timeout = atoi(startup_timeout_str);
startup_timeout = parse_int(startup_timeout_str, "startup timeout");
if (startup_timeout <= 0)
// invalid or negative number
startup_timeout = MAX_STARTUP_TIME_DEFAULT;
Expand Down Expand Up @@ -1652,7 +1652,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Domain UUID option missing!\n");
usage(argv[0]);
}
remote_domain_id = atoi(argv[optind]);
remote_domain_id = parse_int(argv[optind], "remote domain ID");
remote_domain_name = argv[optind+1];
/* this is inserted into the generated command line */
if (!check_single_word(remote_domain_name))
Expand Down

0 comments on commit 856316d

Please sign in to comment.