mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-30 01:05:14 +02:00
Fix SCP stack overflow when copying over directories (#565)
This commit is contained in:
parent
c89890c3a4
commit
ac7bceff6f
79
scp.c
79
scp.c
@ -1262,7 +1262,14 @@ source(int argc, char **argv)
|
|||||||
off_t i, statbytes;
|
off_t i, statbytes;
|
||||||
size_t amt, nr;
|
size_t amt, nr;
|
||||||
int fd = -1, haderr, indx;
|
int fd = -1, haderr, indx;
|
||||||
|
#ifdef WINDOWS
|
||||||
|
/* PATH_MAX is too large on Windows.*/
|
||||||
|
/* Allocate memory dynamically for encname and buf to avoid stack overflow on recursive calls.*/
|
||||||
|
char *last, *name, *buf = NULL, *encname = NULL;
|
||||||
|
size_t encname_len, buf_len, tmp_len;
|
||||||
|
#else
|
||||||
char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX];
|
char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX];
|
||||||
|
#endif
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
for (indx = 0; indx < argc; ++indx) {
|
for (indx = 0; indx < argc; ++indx) {
|
||||||
@ -1274,7 +1281,20 @@ source(int argc, char **argv)
|
|||||||
if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) == -1)
|
if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) == -1)
|
||||||
goto syserr;
|
goto syserr;
|
||||||
if (strchr(name, '\n') != NULL) {
|
if (strchr(name, '\n') != NULL) {
|
||||||
|
#ifdef WINDOWS
|
||||||
|
if (!encname) {
|
||||||
|
encname_len = ((2 * len) < PATH_MAX) ? 2 * len : PATH_MAX;
|
||||||
|
encname = xmalloc(encname_len);
|
||||||
|
}
|
||||||
|
while ((tmp_len = strnvis(encname, name, encname_len, VIS_NL)) >= encname_len) {
|
||||||
|
if (tmp_len >= PATH_MAX)
|
||||||
|
break;
|
||||||
|
encname_len = tmp_len + 1;
|
||||||
|
encname = xreallocarray(encname, encname_len, sizeof(char));
|
||||||
|
}
|
||||||
|
#else
|
||||||
strnvis(encname, name, sizeof(encname), VIS_NL);
|
strnvis(encname, name, sizeof(encname), VIS_NL);
|
||||||
|
#endif
|
||||||
name = encname;
|
name = encname;
|
||||||
}
|
}
|
||||||
if (fstat(fd, &stb) == -1) {
|
if (fstat(fd, &stb) == -1) {
|
||||||
@ -1309,9 +1329,27 @@ syserr: run_err("%s: %s", name, strerror(errno));
|
|||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
|
#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||||
|
#ifdef WINDOWS
|
||||||
|
if (!buf)
|
||||||
|
{
|
||||||
|
/*Set the initial size of buf to "strlen(last) + 20" based on multiple tests that*/
|
||||||
|
/*inidicate that this is usually enough. If not enough, more space will be allocated below.*/
|
||||||
|
buf_len = ((strlen(last) + 20) < PATH_MAX) ? strlen(last) + 20 : PATH_MAX;
|
||||||
|
buf = xmalloc(buf_len);
|
||||||
|
}
|
||||||
|
while ((tmp_len = snprintf(buf, buf_len, "C%04o %lld %s\n",
|
||||||
|
(u_int) (stb.st_mode & FILEMODEMASK),
|
||||||
|
(long long)stb.st_size, last)) >= buf_len) {
|
||||||
|
if (tmp_len >= PATH_MAX)
|
||||||
|
break;
|
||||||
|
buf_len = tmp_len + 1;
|
||||||
|
buf = xreallocarray(buf, buf_len, sizeof(char));
|
||||||
|
}
|
||||||
|
#else
|
||||||
snprintf(buf, sizeof buf, "C%04o %lld %s\n",
|
snprintf(buf, sizeof buf, "C%04o %lld %s\n",
|
||||||
(u_int) (stb.st_mode & FILEMODEMASK),
|
(u_int) (stb.st_mode & FILEMODEMASK),
|
||||||
(long long)stb.st_size, last);
|
(long long)stb.st_size, last);
|
||||||
|
#endif
|
||||||
if (verbose_mode)
|
if (verbose_mode)
|
||||||
fmprintf(stderr, "Sending file modes: %s", buf);
|
fmprintf(stderr, "Sending file modes: %s", buf);
|
||||||
(void) atomicio(vwrite, remout, buf, strlen(buf));
|
(void) atomicio(vwrite, remout, buf, strlen(buf));
|
||||||
@ -1363,6 +1401,12 @@ next: if (fd != -1) {
|
|||||||
if (showprogress)
|
if (showprogress)
|
||||||
stop_progress_meter();
|
stop_progress_meter();
|
||||||
}
|
}
|
||||||
|
#ifdef WINDOWS
|
||||||
|
if (encname)
|
||||||
|
free(encname);
|
||||||
|
if (buf)
|
||||||
|
free(buf);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1370,7 +1414,16 @@ rsource(char *name, struct stat *statp)
|
|||||||
{
|
{
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
|
#ifndef WINDOWS
|
||||||
char *last, *vect[1], path[PATH_MAX];
|
char *last, *vect[1], path[PATH_MAX];
|
||||||
|
#else
|
||||||
|
/* PATH_MAX is too large on Windows.*/
|
||||||
|
/* Allocate memory dynamically for path to avoid stack overflow on recursive calls.*/
|
||||||
|
char *last, *vect[1], *path;
|
||||||
|
size_t path_len = 260, len;
|
||||||
|
|
||||||
|
path = xmalloc(path_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!(dirp = opendir(name))) {
|
if (!(dirp = opendir(name))) {
|
||||||
run_err("%s: %s", name, strerror(errno));
|
run_err("%s: %s", name, strerror(errno));
|
||||||
@ -1387,8 +1440,19 @@ rsource(char *name, struct stat *statp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef WINDOWS
|
||||||
|
while ((len = snprintf(path, path_len, "D%04o %d %.1024s\n",
|
||||||
|
(u_int)(statp->st_mode & FILEMODEMASK), 0, last)) >= path_len)
|
||||||
|
{
|
||||||
|
if (len >= PATH_MAX)
|
||||||
|
break;
|
||||||
|
path_len = len + 1;
|
||||||
|
path = xreallocarray(path, path_len, sizeof(char));
|
||||||
|
}
|
||||||
|
#else
|
||||||
(void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
|
(void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
|
||||||
(u_int) (statp->st_mode & FILEMODEMASK), 0, last);
|
(u_int) (statp->st_mode & FILEMODEMASK), 0, last);
|
||||||
|
#endif
|
||||||
if (verbose_mode)
|
if (verbose_mode)
|
||||||
fmprintf(stderr, "Entering directory: %s", path);
|
fmprintf(stderr, "Entering directory: %s", path);
|
||||||
(void) atomicio(vwrite, remout, path, strlen(path));
|
(void) atomicio(vwrite, remout, path, strlen(path));
|
||||||
@ -1401,14 +1465,29 @@ rsource(char *name, struct stat *statp)
|
|||||||
continue;
|
continue;
|
||||||
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
|
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
|
||||||
continue;
|
continue;
|
||||||
|
#ifdef WINDOWS
|
||||||
|
if (strlen(name) + 1 + strlen(dp->d_name) >= PATH_MAX - 1) {
|
||||||
|
#else
|
||||||
if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
|
if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
|
||||||
|
#endif
|
||||||
run_err("%s/%s: name too long", name, dp->d_name);
|
run_err("%s/%s: name too long", name, dp->d_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#ifdef WINDOWS
|
||||||
|
while ((len = snprintf(path, path_len, "%s/%s", name, dp->d_name)) >= path_len) {
|
||||||
|
path_len = len + 1;
|
||||||
|
path = xreallocarray(path, path_len, sizeof(char));
|
||||||
|
}
|
||||||
|
#else
|
||||||
(void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
|
(void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
|
||||||
|
#endif
|
||||||
vect[0] = path;
|
vect[0] = path;
|
||||||
source(1, vect);
|
source(1, vect);
|
||||||
}
|
}
|
||||||
|
#ifdef WINDOWS
|
||||||
|
if (path)
|
||||||
|
free(path);
|
||||||
|
#endif
|
||||||
(void) closedir(dirp);
|
(void) closedir(dirp);
|
||||||
(void) atomicio(vwrite, remout, "E\n", 2);
|
(void) atomicio(vwrite, remout, "E\n", 2);
|
||||||
(void) response();
|
(void) response();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user