char *user;
char *host;
{
- size_t len;
+ size_t len, n;
int subst;
- char *p, *np, *new_prompt;
+ char *p, *np, *new_prompt, *endp;
/* How much space do we need to malloc for the prompt? */
subst = 0;
}
if (subst) {
- new_prompt = (char *) emalloc(len + 1);
+ new_prompt = (char *) emalloc(++len);
+ *new_prompt = '\0';
+ endp = new_prompt + len - 1;
for (p = old_prompt, np = new_prompt; *p; p++) {
if (p[0] =='%') {
switch (p[1]) {
case 'h':
p++;
- strcpy(np, user_shost);
- np += strlen(user_shost);
+ if ((n = strlcat(new_prompt, user_shost, len)) >= len)
+ goto oflow;
+ np += n;
continue;
case 'H':
p++;
- strcpy(np, user_host);
- np += strlen(user_host);
+ if ((n = strlcat(new_prompt, user_host, len)) >= len)
+ goto oflow;
+ np += n;
continue;
case 'u':
p++;
- strcpy(np, user_name);
- np += strlen(user_name);
+ if ((n = strlcat(new_prompt, user_name, len)) >= len)
+ goto oflow;
+ np += n;
continue;
case 'U':
p++;
- strcpy(np, *user_runas);
- np += strlen(*user_runas);
+ if ((n = strlcat(new_prompt, *user_runas, len)) >= len)
+ goto oflow;
+ np += n;
continue;
case '%':
/* convert %% -> % */
break;
}
}
+ if (np >= endp)
+ goto oflow;
*np++ = *p;
}
*np = '\0';
new_prompt = old_prompt;
return(new_prompt);
+
+oflow:
+ /* We pre-allocate enough space, so this should never happen. */
+ (void) fprintf(stderr, "%s: internal error, expand_prompt() overflow\n",
+ Argv[0]);
+ exit(1);
}
/*
char *var;
char *val;
{
- char *estring, *p;
- size_t varlen, vallen;
-
- varlen = strlen(var);
- vallen = strlen(val);
- p = estring = (char *) emalloc(varlen + vallen + 2);
- strcpy(p, var);
- p += varlen;
- *p++ = '=';
- strcpy(p, val);
+ char *estring;
+ size_t esize;
+
+ esize = strlen(var) + 1 + strlen(val) + 1;
+ estring = (char *) emalloc(esize);
+
+ /* We pre-allocate enough space, so this should never overflow. */
+ if (strlcpy(estring, var, esize) >= esize ||
+ strlcat(estring, "=", esize) >= esize ||
+ strlcat(estring, val, esize) >= esize) {
+ (void) fprintf(stderr, "%s: internal error, format_env() overflow\n",
+ Argv[0]);
+ exit(1);
+ }
return(estring);
}
char *origpath; /* so we can free path later */
char *result = NULL; /* result of path/file lookup */
int checkdot = 0; /* check current dir? */
+ int len; /* length parameter */
if (strlen(infile) >= MAXPATHLEN) {
(void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
* there is no need to look at $PATH.
*/
if (strchr(infile, '/')) {
- (void) strcpy(command, infile);
+ strlcpy(command, infile, sizeof(command)); /* paranoia */
if (sudo_goodpath(command)) {
*outfile = command;
return(FOUND);
/*
* Resolve the path and exit the loop if found.
*/
- if (strlen(path) + strlen(infile) + 1 >= MAXPATHLEN) {
+ len = snprintf(command, sizeof(command), "%s/%s", path, infile);
+ if (len <= 0 || len >= sizeof(command)) {
(void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
exit(1);
}
- (void) sprintf(command, "%s/%s", path, infile);
if ((result = sudo_goodpath(command)))
break;
while ((dent = readdir(dirp)) != NULL) {
/* ignore paths > MAXPATHLEN (XXX - log) */
- if (plen + NAMLEN(dent) >= sizeof(buf))
+ if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf) ||
+ strlcat(buf, dent->d_name, sizeof(buf)) >= sizeof(buf))
continue;
- strcpy(buf, path);
- strcat(buf, dent->d_name);
/* only stat if basenames are the same */
if (strcmp(cmnd_base, dent->d_name) != 0 || stat(buf, &pst) == -1)
/* Assumes dst will be NULL if not set. */
if (dst == NULL) {
dst = (char *) emalloc(BUFSIZ);
+ *dst = '\0';
*dst_size = BUFSIZ;
*dst_len = 0;
*dstp = dst;
}
/* Copy src -> dst adding a separator if appropriate and adjust len. */
- dst += *dst_len;
- *dst_len += src_len;
- *dst = '\0';
if (separator)
- (void) strcat(dst, separator);
- (void) strcat(dst, src);
+ (void) strlcat(dst, separator, *dst_size);
+ (void) strlcat(dst, src, *dst_size);
+ *dst_len += src_len;
}
/*
/* Default value for cmnd and cwd, overridden later. */
if (user_cmnd == NULL)
user_cmnd = NewArgv[0];
- (void) strcpy(user_cwd, "unknown");
+ (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd));
/*
* We avoid gethostbyname() if possible since we don't want
if (!getcwd(user_cwd, sizeof(user_cwd))) {
(void) fprintf(stderr, "%s: Can't get working directory!\n",
Argv[0]);
- (void) strcpy(user_cwd, "unknown");
+ (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd));
}
} else
set_perms(PERM_ROOT);
/* set user_args */
if (NewArgc > 1) {
char *to, **from;
- size_t size;
+ size_t size, n;
/* If MODE_SHELL not set then NewArgv is contiguous so just count */
if (!(sudo_mode & MODE_SHELL)) {
}
/* alloc and copy. */
- to = user_args = (char *) emalloc(size);
- for (from = NewArgv + 1; *from; from++) {
- (void) strcpy(to, *from);
- to += strlen(*from);
+ user_args = (char *) emalloc(size);
+ for (to = user_args, from = NewArgv + 1; *from; from++) {
+ n = strlcpy(to, *from, size - (to - user_args));
+ if (n >= size) {
+ (void) fprintf(stderr,
+ "%s: internal error, init_vars() overflow\n", Argv[0]);
+ exit(1);
+ }
+ to += n;
*to++ = ' ';
}
*--to = '\0';
/* Fill in cmnd_args from NewArgv. */
if (NewArgc > 1) {
- size_t size;
char *to, **from;
+ size_t size, n;
- size = (size_t) NewArgv[NewArgc-1] + strlen(NewArgv[NewArgc-1]) -
- (size_t) NewArgv[1] + 1;
+ size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) +
+ strlen(NewArgv[NewArgc-1]) + 1;
user_args = (char *) emalloc(size);
- for (to = user_args, from = &NewArgv[1]; *from; from++) {
+ for (to = user_args, from = NewArgv + 1; *from; from++) {
+ n = strlcpy(to, *from, size - (to - user_args));
+ if (n >= size) {
+ (void) fprintf(stderr,
+ "%s: internal error, init_vars() overflow\n", Argv[0]);
+ exit(1);
+ }
+ to += n;
*to++ = ' ';
- (void) strcpy(to, *from);
- to += strlen(*from);
}
+ *--to = '\0';
}
/* Initialize default values. */