canon_pp: Avoid buffer overflow if pathname exceeds PATH_MAX

If the weights file pathname is longer than PATH_MAX, it may be written
past the end of the buffer on the stack; or it may be truncated when it
is written to allocated memory (such that it is not null-terminated).

Adjust the code to fix both issues. Dynamically allocate memory for the
actual length of the pathname so that it is not constrained by PATH_MAX.
merge-requests/702/head
David Ward 2022-03-08 19:00:00 -05:00
rodzic 9cd8f475eb
commit 0c70fd560c
1 zmienionych plików z 14 dodań i 11 usunięć

Wyświetl plik

@ -1787,7 +1787,9 @@ static int init_cal(char *file)
************************************************************************/
static SANE_Status fix_weights_file(CANONP_Scanner *cs)
{
char *tmp, *myhome, buf[PATH_MAX];
static const char default_weights_file_prefix[] =
"~/.sane/canon_pp-calibration-";
char *tmp, *myhome;
int i;
struct stat *f_stat;
@ -1804,31 +1806,32 @@ static SANE_Status fix_weights_file(CANONP_Scanner *cs)
if (cs->weights_file == NULL)
{
/* Will be of form canon_pp-calibration-parport0 or -0x378 */
sprintf(buf, "~/.sane/canon_pp-calibration-%s",
/* Form is ~/.sane/canon_pp-calibration-parport0 or -0x378 */
i = strlen(default_weights_file_prefix) +
strlen(cs->params.port->name);
if ((cs->weights_file = malloc(i + 1)) == NULL)
return SANE_STATUS_NO_MEM;
sprintf(cs->weights_file, "%s%s", default_weights_file_prefix,
cs->params.port->name);
cs->weights_file = strdup(buf);
}
/* Get the user's home dir if they used ~ */
if (cs->weights_file[0] == '~')
{
if ((tmp = malloc(PATH_MAX)) == NULL)
return SANE_STATUS_NO_MEM;
if ((myhome = getenv("HOME")) == NULL)
{
DBG(0,"fix_weights_file: FATAL: ~ used, but $HOME not"
" set!\n");
free(tmp);
tmp = NULL;
return SANE_STATUS_INVAL;
}
strncpy(tmp, myhome, PATH_MAX);
strncpy(tmp+strlen(tmp), (cs->weights_file)+1,
PATH_MAX-strlen(tmp));
i = strlen(myhome) + strlen(&cs->weights_file[1]);
if ((tmp = malloc(i + 1)) == NULL)
return SANE_STATUS_NO_MEM;
sprintf(tmp, "%s%s", myhome, &cs->weights_file[1]);
free(cs->weights_file);
cs->weights_file = tmp;
tmp = NULL;
}
if ((f_stat = malloc(sizeof(*f_stat))) == NULL)