Compare commits
No commits in common. "3aa6b701da70ee1585b9f9af0f73b9b348b0ae07" and "90850f451bc1a40de3f420f05ee3065c0bb85317" have entirely different histories.
3aa6b701da
...
90850f451b
81
Fix-Gcc-warnings-for-strncpy-and-strncat.patch
Normal file
81
Fix-Gcc-warnings-for-strncpy-and-strncat.patch
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
From 22ad4f7200a56da969e9296d8fecf2f0b8368afc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dan Yeaw <dyeaw@ford.com>
|
||||||
|
Date: Mon, 23 Dec 2019 15:31:04 -0500
|
||||||
|
Subject: [PATCH] Bootloader: Fix GCC warnings for strncpy and strncat.
|
||||||
|
|
||||||
|
Fixes Issue #4196. GCC 8.1 and later added checks to prevent using
|
||||||
|
strncpy and strncat with the bounds depending on the length of the
|
||||||
|
source str. In order to fix this, a few approaches were made:
|
||||||
|
1. Where guards already existed to ensure that added paths weren't
|
||||||
|
larger than the PATH_MAX, changed to strcpy / strcat which don't take a
|
||||||
|
length parameter.
|
||||||
|
2. Where path length checks didn't exist, set the bounds of the strncpy
|
||||||
|
and strncat to PATH_MAX.
|
||||||
|
|
||||||
|
Signed-off-by: Dan Yeaw <dyeaw@ford.com>
|
||||||
|
---
|
||||||
|
bootloader/src/pyi_path.c | 7 ++++---
|
||||||
|
bootloader/src/pyi_pythonlib.c | 12 ++++++------
|
||||||
|
2 files changed, 10 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/bootloader/src/pyi_path.c b/bootloader/src/pyi_path.c
|
||||||
|
index a449f79..d36e3d2 100644
|
||||||
|
--- a/bootloader/src/pyi_path.c
|
||||||
|
+++ b/bootloader/src/pyi_path.c
|
||||||
|
@@ -56,7 +56,7 @@ pyi_path_dirname(char *result, const char *path)
|
||||||
|
char *match = NULL;
|
||||||
|
|
||||||
|
/* Copy path to result and then just write '\0' to the place with path separator. */
|
||||||
|
- strncpy(result, path, strlen(path) + 1);
|
||||||
|
+ strncpy(result, path, PATH_MAX);
|
||||||
|
/* Remove separator from the end. */
|
||||||
|
len = strlen(result);
|
||||||
|
|
||||||
|
@@ -143,7 +143,7 @@ pyi_path_join(char *result, const char *path1, const char *path2)
|
||||||
|
memset(result, 0, PATH_MAX);
|
||||||
|
}
|
||||||
|
/* Copy path1 to result without null terminator */
|
||||||
|
- strncpy(result, path1, strlen(path1));
|
||||||
|
+ strcpy(result, path1);
|
||||||
|
/* Append trailing slash if missing. */
|
||||||
|
len = strlen(result);
|
||||||
|
|
||||||
|
@@ -156,7 +156,8 @@ pyi_path_join(char *result, const char *path1, const char *path2)
|
||||||
|
|
||||||
|
if (path2[len - 1] == PYI_SEP) {
|
||||||
|
/* Append path2 without slash. */
|
||||||
|
- strncat(result, path2, len - 2);
|
||||||
|
+ strcat(result, path2);
|
||||||
|
+ result[strlen(result) - 1] = PYI_NULLCHAR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* path2 does not end with slash. */
|
||||||
|
diff --git a/bootloader/src/pyi_pythonlib.c b/bootloader/src/pyi_pythonlib.c
|
||||||
|
index ee4b3b2..d90c239 100644
|
||||||
|
--- a/bootloader/src/pyi_pythonlib.c
|
||||||
|
+++ b/bootloader/src/pyi_pythonlib.c
|
||||||
|
@@ -480,15 +480,15 @@ pyi_pylib_start_python(ARCHIVE_STATUS *status)
|
||||||
|
/* Set sys.path */
|
||||||
|
if (is_py2) {
|
||||||
|
/* sys.path = [mainpath] */
|
||||||
|
- strncpy(pypath, status->mainpath, strlen(status->mainpath));
|
||||||
|
+ strncpy(pypath, status->mainpath, PATH_MAX);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* sys.path = [base_library, mainpath] */
|
||||||
|
- strncpy(pypath, status->mainpath, strlen(status->mainpath));
|
||||||
|
- strncat(pypath, PYI_SEPSTR, strlen(PYI_SEPSTR));
|
||||||
|
- strncat(pypath, "base_library.zip", strlen("base_library.zip"));
|
||||||
|
- strncat(pypath, PYI_PATHSEPSTR, strlen(PYI_PATHSEPSTR));
|
||||||
|
- strncat(pypath, status->mainpath, strlen(status->mainpath));
|
||||||
|
+ strncpy(pypath, status->mainpath, PATH_MAX);
|
||||||
|
+ strncat(pypath, PYI_SEPSTR, PATH_MAX);
|
||||||
|
+ strncat(pypath, "base_library.zip", PATH_MAX);
|
||||||
|
+ strncat(pypath, PYI_PATHSEPSTR, PATH_MAX);
|
||||||
|
+ strncat(pypath, status->mainpath, PATH_MAX);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
BIN
PyInstaller-3.6.tar.gz
Normal file
BIN
PyInstaller-3.6.tar.gz
Normal file
Binary file not shown.
63
Reimplement-pyi-search-path-using-strtok.patch
Normal file
63
Reimplement-pyi-search-path-using-strtok.patch
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
From a95fbb0f497680cce0a097aa3a143e84943b903f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
Date: Sun, 3 May 2020 15:26:43 +0200
|
||||||
|
Subject: [PATCH] Bootloader: Reimplement pyi_search_path using strtok().
|
||||||
|
|
||||||
|
This avoids some places where we need to cope with strncpy(= and related. Also
|
||||||
|
the implementation becomes much simpler.
|
||||||
|
---
|
||||||
|
bootloader/src/pyi_path.c | 34 +++++++---------------------------
|
||||||
|
1 file changed, 7 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/bootloader/src/pyi_path.c b/bootloader/src/pyi_path.c
|
||||||
|
index 8736de8cc5..fb417e9269 100644
|
||||||
|
--- a/bootloader/src/pyi_path.c
|
||||||
|
+++ b/bootloader/src/pyi_path.c
|
||||||
|
@@ -205,40 +205,20 @@ pyi_path_exists(char * path)
|
||||||
|
int
|
||||||
|
pyi_search_path(char * result, const char * appname)
|
||||||
|
{
|
||||||
|
- char * path = pyi_getenv("PATH");
|
||||||
|
- char dirname[PATH_MAX + 1];
|
||||||
|
- char filename[PATH_MAX + 1];
|
||||||
|
+ char *path = pyi_getenv("PATH"); // returns a copy
|
||||||
|
+ char *dirname;
|
||||||
|
|
||||||
|
if (NULL == path) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- while (1) {
|
||||||
|
- char *delim = strchr(path, PYI_PATHSEP);
|
||||||
|
-
|
||||||
|
- if (delim) {
|
||||||
|
- size_t len = delim - path;
|
||||||
|
-
|
||||||
|
- if (len > PATH_MAX) {
|
||||||
|
- len = PATH_MAX;
|
||||||
|
- }
|
||||||
|
- strncpy(dirname, path, len);
|
||||||
|
- *(dirname + len) = '\0';
|
||||||
|
- }
|
||||||
|
- else { /* last $PATH element */
|
||||||
|
- strncpy(dirname, path, PATH_MAX);
|
||||||
|
- }
|
||||||
|
- pyi_path_join(filename, dirname, appname);
|
||||||
|
-
|
||||||
|
- if (pyi_path_exists(filename)) {
|
||||||
|
- strncpy(result, filename, PATH_MAX);
|
||||||
|
+ dirname = strtok(path, PYI_PATHSEPSTR);
|
||||||
|
+ while (dirname != NULL) {
|
||||||
|
+ pyi_path_join(result, dirname, appname);
|
||||||
|
+ if (pyi_path_exists(result)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- if (!delim) {
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- path = delim + 1;
|
||||||
|
+ dirname = strtok(NULL, PYI_PATHSEPSTR);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
208
Use-snprintf-to-simplify-some-string-len.patch
Normal file
208
Use-snprintf-to-simplify-some-string-len.patch
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
From b4c0d01e751975090fa7346a2a71dd778c3b412c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||||
|
Date: Sun, 3 May 2020 15:43:52 +0200
|
||||||
|
Subject: [PATCH] Bootloader: Use snprintf() to simplify some string length
|
||||||
|
checks.
|
||||||
|
|
||||||
|
Instead of copying strings and checking whether the string si terminated with
|
||||||
|
a Null bytes, use snprintf, which tells how much space the new string would
|
||||||
|
have taken and compare this to the available space.
|
||||||
|
|
||||||
|
Since snprintf() add some overhead, This code might be a bit less efficient.
|
||||||
|
But this sie the bootloader, and most of the functions are called once only.
|
||||||
|
---
|
||||||
|
bootloader/src/pyi_archive.c | 21 ++++++++-------------
|
||||||
|
bootloader/src/pyi_launch.c | 27 +++++++++------------------
|
||||||
|
bootloader/src/pyi_main.c | 4 ++--
|
||||||
|
bootloader/src/pyi_path.c | 3 +--
|
||||||
|
bootloader/src/pyi_pythonlib.c | 14 +++++++++-----
|
||||||
|
bootloader/src/pyi_utils.c | 7 ++-----
|
||||||
|
6 files changed, 31 insertions(+), 45 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/bootloader/src/pyi_archive.c b/bootloader/src/pyi_archive.c
|
||||||
|
index ed886e09fb..32b129fb98 100644
|
||||||
|
--- a/bootloader/src/pyi_archive.c
|
||||||
|
+++ b/bootloader/src/pyi_archive.c
|
||||||
|
@@ -455,28 +455,23 @@ int
|
||||||
|
pyi_arch_set_paths(ARCHIVE_STATUS *status, char const * archivePath,
|
||||||
|
char const * archiveName)
|
||||||
|
{
|
||||||
|
- size_t pathlen, namelen;
|
||||||
|
-
|
||||||
|
- pathlen = strnlen(archivePath, PATH_MAX);
|
||||||
|
- namelen = strnlen(archiveName, PATH_MAX);
|
||||||
|
-
|
||||||
|
- if (pathlen+namelen+1 > PATH_MAX) {
|
||||||
|
- return -1;
|
||||||
|
+ /* Set homepath to where the archive is */
|
||||||
|
+ if (snprintf(status->homepath, PATH_MAX, "%s", archivePath) >= PATH_MAX) {
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the archive Path */
|
||||||
|
- strcpy(status->archivename, archivePath);
|
||||||
|
- strcat(status->archivename, archiveName);
|
||||||
|
-
|
||||||
|
- /* Set homepath to where the archive is */
|
||||||
|
- strcpy(status->homepath, archivePath);
|
||||||
|
+ if (snprintf(status->archivename, PATH_MAX,
|
||||||
|
+ "%s%s", archivePath, archiveName) >= PATH_MAX) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initial value of mainpath is homepath. It might be overriden
|
||||||
|
* by temppath if it is available.
|
||||||
|
*/
|
||||||
|
status->has_temp_directory = false;
|
||||||
|
- strcpy(status->mainpath, status->homepath);
|
||||||
|
+ strcpy(status->mainpath, status->homepath); // homepath fits into PATH_MAX
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/bootloader/src/pyi_launch.c b/bootloader/src/pyi_launch.c
|
||||||
|
index 3517be6353..432a43416f 100644
|
||||||
|
--- a/bootloader/src/pyi_launch.c
|
||||||
|
+++ b/bootloader/src/pyi_launch.c
|
||||||
|
@@ -79,15 +79,13 @@ checkFile(char *buf, const char *fmt, ...)
|
||||||
|
static int
|
||||||
|
splitName(char *path, char *filename, const char *item)
|
||||||
|
{
|
||||||
|
- char name[PATH_MAX + 1];
|
||||||
|
+ char name[PATH_MAX];
|
||||||
|
|
||||||
|
VS("LOADER: Splitting item into path and filename\n");
|
||||||
|
- strncpy(name, item, PATH_MAX + 1);
|
||||||
|
-
|
||||||
|
- if (name[PATH_MAX] != '\0') {
|
||||||
|
+ if (snprintf(name, PATH_MAX, "%s", item) >= PATH_MAX) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ // `name` fits into PATH_MAX, so will all substrings
|
||||||
|
strcpy(path, strtok(name, ":"));
|
||||||
|
strcpy(filename, strtok(NULL, ":"));
|
||||||
|
|
||||||
|
@@ -148,13 +146,11 @@ _get_archive(ARCHIVE_STATUS *archive_pool[], const char *path)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- strncpy(archive->archivename, path, PATH_MAX);
|
||||||
|
- strncpy(archive->homepath, archive_pool[SELF]->homepath, PATH_MAX);
|
||||||
|
- strncpy(archive->temppath, archive_pool[SELF]->temppath, PATH_MAX);
|
||||||
|
-
|
||||||
|
- if (archive->archivename[PATH_MAX-1] != '\0'
|
||||||
|
- || archive->homepath[PATH_MAX-1] != '\0'
|
||||||
|
- || archive->temppath[PATH_MAX-1] != '\0') {
|
||||||
|
+ if ((snprintf(archive->archivename, PATH_MAX, "%s", path) >= PATH_MAX) ||
|
||||||
|
+ (snprintf(archive->homepath, PATH_MAX, "%s",
|
||||||
|
+ archive_pool[SELF]->homepath) >= PATH_MAX) ||
|
||||||
|
+ (snprintf(archive->temppath, PATH_MAX, "%s",
|
||||||
|
+ archive_pool[SELF]->temppath) >= PATH_MAX)) {
|
||||||
|
FATALERROR("Archive path exceeds PATH_MAX\n");
|
||||||
|
free(archive);
|
||||||
|
return NULL;
|
||||||
|
@@ -369,7 +365,6 @@ pyi_launch_run_scripts(ARCHIVE_STATUS *status)
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
- size_t namelen;
|
||||||
|
TOC * ptoc = status->tocbuff;
|
||||||
|
PyObject *__main__;
|
||||||
|
PyObject *__file__;
|
||||||
|
@@ -400,14 +395,10 @@ pyi_launch_run_scripts(ARCHIVE_STATUS *status)
|
||||||
|
data = pyi_arch_extract(status, ptoc);
|
||||||
|
/* Set the __file__ attribute within the __main__ module,
|
||||||
|
* for full compatibility with normal execution. */
|
||||||
|
- namelen = strnlen(ptoc->name, PATH_MAX);
|
||||||
|
- if (namelen >= PATH_MAX-strlen(".py")-1) {
|
||||||
|
+ if (snprintf(buf, PATH_MAX, "%s.py", ptoc->name) >= PATH_MAX) {
|
||||||
|
FATALERROR("Name exceeds PATH_MAX\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- strcpy(buf, ptoc->name);
|
||||||
|
- strcat(buf, ".py");
|
||||||
|
VS("LOADER: Running %s\n", buf);
|
||||||
|
|
||||||
|
if (is_py2) {
|
||||||
|
diff --git a/bootloader/src/pyi_main.c b/bootloader/src/pyi_main.c
|
||||||
|
index 02b1bec5dc..472cd1ae9a 100644
|
||||||
|
--- a/bootloader/src/pyi_main.c
|
||||||
|
+++ b/bootloader/src/pyi_main.c
|
||||||
|
@@ -126,8 +126,8 @@ pyi_main(int argc, char * argv[])
|
||||||
|
* we pass it through status variable
|
||||||
|
*/
|
||||||
|
if (strcmp(homepath, extractionpath) != 0) {
|
||||||
|
- strncpy(archive_status->temppath, extractionpath, PATH_MAX);
|
||||||
|
- if (archive_status->temppath[PATH_MAX-1] != '\0') {
|
||||||
|
+ if (snprintf(archive_status->temppath, PATH_MAX,
|
||||||
|
+ "%s", extractionpath) >= PATH_MAX) {
|
||||||
|
VS("LOADER: temppath exceeds PATH_MAX\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
diff --git a/bootloader/src/pyi_path.c b/bootloader/src/pyi_path.c
|
||||||
|
index fb417e9269..6ed252ffab 100644
|
||||||
|
--- a/bootloader/src/pyi_path.c
|
||||||
|
+++ b/bootloader/src/pyi_path.c
|
||||||
|
@@ -286,8 +286,7 @@ pyi_path_executable(char *execfile, const char *appname)
|
||||||
|
if (-1 == result) {
|
||||||
|
/* Searching $PATH failed, user is crazy. */
|
||||||
|
VS("LOADER: Searching $PATH failed for %s", appname);
|
||||||
|
- strncpy(buffer, appname, PATH_MAX);
|
||||||
|
- if (buffer[PATH_MAX-1] != '\0') {
|
||||||
|
+ if (snprintf(buffer, PATH_MAX, "%s", "appname") >= PATH_MAX) {
|
||||||
|
VS("LOADER: Appname too large %s\n", appname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
diff --git a/bootloader/src/pyi_pythonlib.c b/bootloader/src/pyi_pythonlib.c
|
||||||
|
index caffcd6daa..8144885b17 100644
|
||||||
|
--- a/bootloader/src/pyi_pythonlib.c
|
||||||
|
+++ b/bootloader/src/pyi_pythonlib.c
|
||||||
|
@@ -414,18 +414,16 @@ pyi_pylib_start_python(ARCHIVE_STATUS *status)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set sys.path */
|
||||||
|
- if (is_py2) {
|
||||||
|
- /* sys.path = [mainpath] */
|
||||||
|
- strncpy(pypath, status->mainpath, PATH_MAX);
|
||||||
|
- }
|
||||||
|
- else {
|
||||||
|
- /* sys.path = [base_library, mainpath] */
|
||||||
|
+ /* sys.path = [base_library, mainpath] */
|
||||||
|
- strncpy(pypath, status->mainpath, PATH_MAX);
|
||||||
|
- strncat(pypath, PYI_SEPSTR, PATH_MAX);
|
||||||
|
- strncat(pypath, "base_library.zip", PATH_MAX);
|
||||||
|
- strncat(pypath, PYI_PATHSEPSTR, PATH_MAX);
|
||||||
|
- strncat(pypath, status->mainpath, PATH_MAX);
|
||||||
|
- };
|
||||||
|
+ if (snprintf(pypath, sizeof pypath, "%s%cbase_library.zip%c%s",
|
||||||
|
+ status->mainpath, PYI_SEP, PYI_PATHSEP, status->mainpath)
|
||||||
|
+ >= sizeof pypath) {
|
||||||
|
+ // This should never happen, since mainpath is < PATH_MAX and pypath is
|
||||||
|
+ // huge enough
|
||||||
|
+ FATALERROR("sys.path (based on %s) exceeds buffer[%d] space\n",
|
||||||
|
+ status->mainpath, sizeof pypath);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Python 3, we must set sys.path to have base_library.zip before
|
||||||
|
diff --git a/bootloader/src/pyi_utils.c b/bootloader/src/pyi_utils.c
|
||||||
|
index e18d611f26..0c89975908 100644
|
||||||
|
--- a/bootloader/src/pyi_utils.c
|
||||||
|
+++ b/bootloader/src/pyi_utils.c
|
||||||
|
@@ -557,11 +557,8 @@ pyi_open_target(const char *path, const char* name_)
|
||||||
|
char *dir;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
- strncpy(fnm, path, PATH_MAX);
|
||||||
|
- strncpy(name, name_, PATH_MAX);
|
||||||
|
-
|
||||||
|
- /* Check if the path names could be copied */
|
||||||
|
- if (fnm[PATH_MAX-1] != '\0' || name[PATH_MAX-1] != '\0') {
|
||||||
|
+ if (snprintf(fnm, PATH_MAX, "%s", path) >= PATH_MAX ||
|
||||||
|
+ snprintf(name, PATH_MAX, "%s", name_) >= PATH_MAX) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
From 709262381451878dadb9e9d26190167a2ab5e67c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rok Mandeljc <rok.mandeljc@gmail.com>
|
|
||||||
Date: Thu, 3 Aug 2023 13:49:03 +0200
|
|
||||||
Subject: [PATCH] rthooks: win32com: fully isolate the genpy cache
|
|
||||||
|
|
||||||
Instead of extending the `win32.com.gen_py` sub-module search paths
|
|
||||||
(the `__path__` attribute) with the new location of the isolated
|
|
||||||
cache, override it completely. This prevents the global cache from
|
|
||||||
being accessed, which might result in errors when the global cache
|
|
||||||
contains some, but not all, required modules.
|
|
||||||
---
|
|
||||||
.../hooks/rthooks/pyi_rth_win32comgenpy.py | 44 +++++++------------
|
|
||||||
news/6257.bugfix.rst | 3 ++
|
|
||||||
2 files changed, 18 insertions(+), 29 deletions(-)
|
|
||||||
create mode 100644 news/6257.bugfix.rst
|
|
||||||
|
|
||||||
diff --git a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py
|
|
||||||
index 3671c3ab2e..aed2515b08 100644
|
|
||||||
--- a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py
|
|
||||||
+++ b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py
|
|
||||||
@@ -9,12 +9,12 @@
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-# The win32.client.gencache code must be allowed to create the cache in %temp% (user's temp). It is necessary to get the
|
|
||||||
-# gencache code to use a suitable directory other than the default in lib\site-packages\win32com\client\gen_py.
|
|
||||||
-# PyInstaller does not provide this directory structure and the frozen executable could be placed in a non-writable
|
|
||||||
-# directory like 'C:\Program Files. That's the reason for %temp% directory.
|
|
||||||
-#
|
|
||||||
-# http://www.py2exe.org/index.cgi/UsingEnsureDispatch
|
|
||||||
+# Put the cache generated by `win32com.client.gencache` into isolated temporary directory. Historically, this was
|
|
||||||
+# required due to earlier versions of `pywin32` using the `site-packages\win32com\client\gen_py` directory for
|
|
||||||
+# the cache by default. Nowadays, the default location for the cache seems to be in the configured temporary directory
|
|
||||||
+# (pointed to by TEMP or TMP, for example %LOCALAPPDATA%\Temp), so strictly speaking, the relocation is not necessary
|
|
||||||
+# anymore. But for the time being, we are keeping it around to isolate the frozen application from the rest of the
|
|
||||||
+# system.
|
|
||||||
|
|
||||||
|
|
||||||
def _pyi_rthook():
|
|
||||||
@@ -23,36 +23,22 @@ def _pyi_rthook():
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
- # Put gen_py cache in temp directory.
|
|
||||||
+ import win32com
|
|
||||||
+
|
|
||||||
+ # Create temporary directory. The actual cache directory needs to be named `gen_py`, so create a sub-directory.
|
|
||||||
supportdir = tempfile.mkdtemp()
|
|
||||||
- # gen_py has to be put into directory 'gen_py'.
|
|
||||||
+
|
|
||||||
genpydir = os.path.join(supportdir, 'gen_py')
|
|
||||||
+ os.makedirs(genpydir, exist_ok=True)
|
|
||||||
|
|
||||||
- # Create 'gen_py' directory. This directory does not need to contain '__init__.py' file.
|
|
||||||
- try:
|
|
||||||
- # win32com gencache cannot be put directly to 'supportdir' with any random name. It has to be put in a directory
|
|
||||||
- # called 'gen_py'. This is the reason why to create this directory in supportdir'.
|
|
||||||
- os.makedirs(genpydir)
|
|
||||||
- # Remove temp directory at application exit and ignore any errors.
|
|
||||||
- atexit.register(shutil.rmtree, supportdir, ignore_errors=True)
|
|
||||||
- except OSError:
|
|
||||||
- pass
|
|
||||||
+ # Remove the teporary directory at application exit, ignoring errors.
|
|
||||||
+ atexit.register(shutil.rmtree, supportdir, ignore_errors=True)
|
|
||||||
|
|
||||||
# Override the default path to gen_py cache.
|
|
||||||
- import win32com # noqa: E402
|
|
||||||
-
|
|
||||||
win32com.__gen_path__ = genpydir
|
|
||||||
|
|
||||||
- # The attribute __loader__ makes module 'pkg_resources' working but On Windows it breaks pywin32 (win32com) and test
|
|
||||||
- # 'basic/test_pyttsx' will fail. Just removing that attribute for win32com fixes that and gencache is created
|
|
||||||
- # properly.
|
|
||||||
- if hasattr(win32com, '__loader__'):
|
|
||||||
- del win32com.__loader__
|
|
||||||
-
|
|
||||||
- # Ensure genpydir is in 'gen_py' module paths.
|
|
||||||
- import win32com.gen_py # noqa: E402
|
|
||||||
-
|
|
||||||
- win32com.gen_py.__path__.insert(0, genpydir)
|
|
||||||
+ # Override the sub-module paths for win32com.gen_py run-time sub-package.
|
|
||||||
+ win32com.gen_py.__path__ = [genpydir]
|
|
||||||
|
|
||||||
|
|
||||||
_pyi_rthook()
|
|
||||||
diff --git a/news/6257.bugfix.rst b/news/6257.bugfix.rst
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..3cb746a332
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/news/6257.bugfix.rst
|
|
||||||
@@ -0,0 +1,3 @@
|
|
||||||
+(Windows) Fix ``win32com`` run-time hook to fully isolate the ``gen_py``
|
|
||||||
+cache. This prevents the access to global cache, which results in errors
|
|
||||||
+when the global cache contains some, but not all, required modules.
|
|
||||||
\ No newline at end of file
|
|
||||||
@ -1,513 +0,0 @@
|
|||||||
From 5a53dc58295b26eb8af1f146df990a657bc916d1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Rok Mandeljc <rok.mandeljc@gmail.com>
|
|
||||||
Date: Sat, 5 Aug 2023 12:50:28 +0200
|
|
||||||
Subject: [PATCH] rthooks: secure temp directories used by matplotlib and
|
|
||||||
win32com rthooks
|
|
||||||
|
|
||||||
The run-time hooks that relocate the package's configuration/cache
|
|
||||||
directory into isolated temporary directory create this directory using
|
|
||||||
the `tempfile.mkdtemp` function. According to its documentation, the
|
|
||||||
function creates the temporary directory "in the most secure manner
|
|
||||||
possible", and the created directory should be "readable, writable, and
|
|
||||||
searchable only by the creating user ID".
|
|
||||||
|
|
||||||
However, this does not apply to Windows, where the 0o700 POSIX
|
|
||||||
permissions mask passed to the underyling `os.mkdir` call has no effect.
|
|
||||||
Consequently, the access to the created temporary directory is in fact
|
|
||||||
gated only by the access to the parent directory. So as long as `TEMP`
|
|
||||||
and `TMP` point to `%LOCALAPPDATA%\Temp`, the created temporary
|
|
||||||
directories are typically inaccessible to other users, who do not have
|
|
||||||
access to the user's home directory. On the other hand, if the temporary
|
|
||||||
directory base is relocated to a system-wide location (e.g., `c:\temp`),
|
|
||||||
the temporary directories created by the run-time hooks might become
|
|
||||||
accessible to other users as well. A malicious user with local access
|
|
||||||
might thus modify the contents of the temporary directory, interfering
|
|
||||||
with the application. If the application is running in privileged mode
|
|
||||||
and developer mode is enabled on the system, they might also attempt
|
|
||||||
a symlink attack due to lack of hardened mode for `shutil.rmtree`
|
|
||||||
(used for clean up) on Windows.
|
|
||||||
|
|
||||||
Therefore, we replace the use of `tempfile.mkdtemp` with custom function
|
|
||||||
that uses original `mkdtemp` on POSIX and provides a Windows-specific
|
|
||||||
implementation that secures the access to created directory via security
|
|
||||||
descriptor passed to the `CreateDirectoryW` call. This is a
|
|
||||||
`ctypes`-based port of the code that we already have in bootloader for
|
|
||||||
mitigating the same issue with temporary directory in onefile builds.
|
|
||||||
|
|
||||||
In order to share the implementation among the two run-time hooks that
|
|
||||||
require it, the code is provided by a new `_pyi_rth_utils` PyInstaller
|
|
||||||
"fake" package, which is bundled with the frozen application on demand
|
|
||||||
(i.e., if it is referenced in any of collected run-time hooks).
|
|
||||||
|
|
||||||
Origin:
|
|
||||||
https://github.com/pyinstaller/pyinstaller/commit/5a53dc58295b26eb8af1f146df990a657bc916d1
|
|
||||||
---
|
|
||||||
MANIFEST.in | 2 +-
|
|
||||||
.../fake-modules/_pyi_rth_utils/__init__.py | 56 ++++
|
|
||||||
.../fake-modules/_pyi_rth_utils/_win32.py | 262 ++++++++++++++++++
|
|
||||||
.../hook-_pyi_rth_utils.py | 25 ++
|
|
||||||
.../hooks/rthooks/pyi_rth_mplconfig.py | 8 +-
|
|
||||||
.../hooks/rthooks/pyi_rth_win32comgenpy.py | 8 +-
|
|
||||||
news/7827.bugfix.rst | 5 +
|
|
||||||
setup.cfg | 1 +
|
|
||||||
setup.py | 1 +
|
|
||||||
9 files changed, 361 insertions(+), 7 deletions(-)
|
|
||||||
create mode 100644 PyInstaller/fake-modules/_pyi_rth_utils/__init__.py
|
|
||||||
create mode 100644 PyInstaller/fake-modules/_pyi_rth_utils/_win32.py
|
|
||||||
create mode 100644 PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py
|
|
||||||
create mode 100644 news/7827.bugfix.rst
|
|
||||||
|
|
||||||
diff --git a/MANIFEST.in b/MANIFEST.in
|
|
||||||
index a77f401..2c702a1 100755
|
|
||||||
--- a/MANIFEST.in
|
|
||||||
+++ b/MANIFEST.in
|
|
||||||
@@ -12,6 +12,6 @@ recursive-include PyInstaller/bootloader/Windows-64bit-intel *
|
|
||||||
recursive-include PyInstaller/bootloader/Darwin-64bit *
|
|
||||||
include pyproject.toml
|
|
||||||
# These files need to be explicitly included
|
|
||||||
-include PyInstaller/fake-modules/*.py
|
|
||||||
+recursive-include PyInstaller/fake-modules *.py
|
|
||||||
include PyInstaller/hooks/rthooks.dat
|
|
||||||
include PyInstaller/lib/README.rst
|
|
||||||
diff --git a/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py b/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..2d3af0e
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py
|
|
||||||
@@ -0,0 +1,56 @@
|
|
||||||
+# -----------------------------------------------------------------------------
|
|
||||||
+# Copyright (c) 2023, PyInstaller Development Team.
|
|
||||||
+#
|
|
||||||
+# Distributed under the terms of the GNU General Public License (version 2
|
|
||||||
+# or later) with exception for distributing the bootloader.
|
|
||||||
+#
|
|
||||||
+# The full license is in the file COPYING.txt, distributed with this software.
|
|
||||||
+#
|
|
||||||
+# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
|
|
||||||
+# -----------------------------------------------------------------------------
|
|
||||||
+
|
|
||||||
+import os
|
|
||||||
+import sys
|
|
||||||
+import errno
|
|
||||||
+import tempfile
|
|
||||||
+
|
|
||||||
+# Helper for creating temporary directories with access restricted to the user running the process.
|
|
||||||
+# On POSIX systems, this is already achieved by `tempfile.mkdtemp`, which uses 0o700 permissions mask.
|
|
||||||
+# On Windows, however, the POSIX permissions semantics have no effect, and we need to provide our own implementation
|
|
||||||
+# that restricts the access by passing appropriate security attributes to the `CreateDirectory` function.
|
|
||||||
+
|
|
||||||
+if os.name == 'nt':
|
|
||||||
+ from . import _win32
|
|
||||||
+
|
|
||||||
+ def secure_mkdtemp(suffix=None, prefix=None, dir=None):
|
|
||||||
+ """
|
|
||||||
+ Windows-specific replacement for `tempfile.mkdtemp` that restricts access to the user running the process.
|
|
||||||
+ Based on `mkdtemp` implementation from python 3.11 stdlib.
|
|
||||||
+ """
|
|
||||||
+
|
|
||||||
+ prefix, suffix, dir, output_type = tempfile._sanitize_params(prefix, suffix, dir)
|
|
||||||
+
|
|
||||||
+ names = tempfile._get_candidate_names()
|
|
||||||
+ if output_type is bytes:
|
|
||||||
+ names = map(os.fsencode, names)
|
|
||||||
+
|
|
||||||
+ for seq in range(tempfile.TMP_MAX):
|
|
||||||
+ name = next(names)
|
|
||||||
+ file = os.path.join(dir, prefix + name + suffix)
|
|
||||||
+ sys.audit("tempfile.mkdtemp", file)
|
|
||||||
+ try:
|
|
||||||
+ _win32.secure_mkdir(file)
|
|
||||||
+ except FileExistsError:
|
|
||||||
+ continue # try again
|
|
||||||
+ except PermissionError:
|
|
||||||
+ # This exception is thrown when a directory with the chosen name already exists on windows.
|
|
||||||
+ if (os.name == 'nt' and os.path.isdir(dir) and os.access(dir, os.W_OK)):
|
|
||||||
+ continue
|
|
||||||
+ else:
|
|
||||||
+ raise
|
|
||||||
+ return file
|
|
||||||
+
|
|
||||||
+ raise FileExistsError(errno.EEXIST, "No usable temporary directory name found")
|
|
||||||
+
|
|
||||||
+else:
|
|
||||||
+ secure_mkdtemp = tempfile.mkdtemp
|
|
||||||
diff --git a/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py b/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..41237fb
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py
|
|
||||||
@@ -0,0 +1,262 @@
|
|
||||||
+# -----------------------------------------------------------------------------
|
|
||||||
+# Copyright (c) 2023, PyInstaller Development Team.
|
|
||||||
+#
|
|
||||||
+# Distributed under the terms of the GNU General Public License (version 2
|
|
||||||
+# or later) with exception for distributing the bootloader.
|
|
||||||
+#
|
|
||||||
+# The full license is in the file COPYING.txt, distributed with this software.
|
|
||||||
+#
|
|
||||||
+# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
|
|
||||||
+# -----------------------------------------------------------------------------
|
|
||||||
+
|
|
||||||
+import ctypes
|
|
||||||
+import ctypes.wintypes
|
|
||||||
+
|
|
||||||
+# Constants from win32 headers
|
|
||||||
+TOKEN_QUERY = 0x0008
|
|
||||||
+
|
|
||||||
+TokenUser = 1 # from TOKEN_INFORMATION_CLASS enum
|
|
||||||
+
|
|
||||||
+ERROR_INSUFFICIENT_BUFFER = 122
|
|
||||||
+
|
|
||||||
+INVALID_HANDLE = -1
|
|
||||||
+
|
|
||||||
+FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
|
|
||||||
+FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
|
||||||
+
|
|
||||||
+SDDL_REVISION1 = 1
|
|
||||||
+
|
|
||||||
+# Structures for ConvertSidToStringSidW
|
|
||||||
+PSID = ctypes.wintypes.LPVOID
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+class SID_AND_ATTRIBUTES(ctypes.Structure):
|
|
||||||
+ _fields_ = [
|
|
||||||
+ ("Sid", PSID),
|
|
||||||
+ ("Attributes", ctypes.wintypes.DWORD),
|
|
||||||
+ ]
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+class TOKEN_USER(ctypes.Structure):
|
|
||||||
+ _fields_ = [
|
|
||||||
+ ("User", SID_AND_ATTRIBUTES),
|
|
||||||
+ ]
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+PTOKEN_USER = ctypes.POINTER(TOKEN_USER)
|
|
||||||
+
|
|
||||||
+# SECURITY_ATTRIBUTES structure for CreateDirectoryW
|
|
||||||
+PSECURITY_DESCRIPTOR = ctypes.wintypes.LPVOID
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+class SECURITY_ATTRIBUTES(ctypes.Structure):
|
|
||||||
+ _fields_ = [
|
|
||||||
+ ("nLength", ctypes.wintypes.DWORD),
|
|
||||||
+ ("lpSecurityDescriptor", PSECURITY_DESCRIPTOR),
|
|
||||||
+ ("bInheritHandle", ctypes.wintypes.BOOL),
|
|
||||||
+ ]
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+# win32 API functions, bound via ctypes.
|
|
||||||
+# NOTE: we do not use ctypes.windll.<dll_name> to avoid modifying its (global) function prototypes, which might affect
|
|
||||||
+# user's code.
|
|
||||||
+kernel32 = ctypes.WinDLL("kernel32")
|
|
||||||
+advapi32 = ctypes.WinDLL("advapi32")
|
|
||||||
+
|
|
||||||
+kernel32.CloseHandle.restype = ctypes.wintypes.BOOL
|
|
||||||
+kernel32.CloseHandle.argtypes = (ctypes.wintypes.HANDLE,)
|
|
||||||
+
|
|
||||||
+kernel32.LocalFree.restype = ctypes.wintypes.BOOL
|
|
||||||
+kernel32.LocalFree.argtypes = (ctypes.wintypes.HLOCAL,)
|
|
||||||
+
|
|
||||||
+kernel32.GetCurrentProcess.restype = ctypes.wintypes.HANDLE
|
|
||||||
+
|
|
||||||
+kernel32.OpenProcessToken.restype = ctypes.wintypes.BOOL
|
|
||||||
+kernel32.OpenProcessToken.argtypes = (
|
|
||||||
+ ctypes.wintypes.HANDLE,
|
|
||||||
+ ctypes.wintypes.DWORD,
|
|
||||||
+ ctypes.wintypes.PHANDLE,
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+advapi32.ConvertSidToStringSidW.restype = ctypes.wintypes.BOOL
|
|
||||||
+advapi32.ConvertSidToStringSidW.argtypes = (
|
|
||||||
+ PSID,
|
|
||||||
+ ctypes.POINTER(ctypes.wintypes.LPWSTR),
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW.restype = ctypes.wintypes.BOOL
|
|
||||||
+advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW.argtypes = (
|
|
||||||
+ ctypes.wintypes.LPCWSTR,
|
|
||||||
+ ctypes.wintypes.DWORD,
|
|
||||||
+ ctypes.POINTER(PSECURITY_DESCRIPTOR),
|
|
||||||
+ ctypes.wintypes.PULONG,
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def _win_error_to_message(error_code):
|
|
||||||
+ """
|
|
||||||
+ Convert win32 error code to message.
|
|
||||||
+ """
|
|
||||||
+ message_wstr = ctypes.wintypes.LPWSTR(None)
|
|
||||||
+ ret = kernel32.FormatMessageW(
|
|
||||||
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
||||||
+ None, # lpSource
|
|
||||||
+ error_code, # dwMessageId
|
|
||||||
+ 0x400, # dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
|
|
||||||
+ ctypes.byref(message_wstr), # pointer to LPWSTR due to FORMAT_MESSAGE_ALLOCATE_BUFFER
|
|
||||||
+ 64, # due to FORMAT_MESSAGE_ALLOCATE_BUFFER, this is minimum number of characters to allocate
|
|
||||||
+ )
|
|
||||||
+ if ret == 0:
|
|
||||||
+ return None
|
|
||||||
+
|
|
||||||
+ message = message_wstr.value
|
|
||||||
+ kernel32.LocalFree(message_wstr)
|
|
||||||
+
|
|
||||||
+ # Strip trailing CR/LF.
|
|
||||||
+ if message:
|
|
||||||
+ message = message.strip()
|
|
||||||
+ return message
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def _get_user_sid():
|
|
||||||
+ """
|
|
||||||
+ Obtain the SID for the current user.
|
|
||||||
+ """
|
|
||||||
+ process_token = ctypes.wintypes.HANDLE(INVALID_HANDLE)
|
|
||||||
+
|
|
||||||
+ try:
|
|
||||||
+ # Get access token for the current process
|
|
||||||
+ ret = kernel32.OpenProcessToken(
|
|
||||||
+ kernel32.GetCurrentProcess(),
|
|
||||||
+ TOKEN_QUERY,
|
|
||||||
+ ctypes.pointer(process_token),
|
|
||||||
+ )
|
|
||||||
+ if ret == 0:
|
|
||||||
+ error_code = kernel32.GetLastError()
|
|
||||||
+ raise RuntimeError(f"Failed to open process token! Error code: 0x{error_code:X}")
|
|
||||||
+
|
|
||||||
+ # Query buffer size for user info structure
|
|
||||||
+ user_info_size = ctypes.wintypes.DWORD(0)
|
|
||||||
+
|
|
||||||
+ ret = advapi32.GetTokenInformation(
|
|
||||||
+ process_token,
|
|
||||||
+ TokenUser,
|
|
||||||
+ None,
|
|
||||||
+ 0,
|
|
||||||
+ ctypes.byref(user_info_size),
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ # We expect this call to fail with ERROR_INSUFFICIENT_BUFFER
|
|
||||||
+ if ret == 0:
|
|
||||||
+ error_code = kernel32.GetLastError()
|
|
||||||
+ if error_code != ERROR_INSUFFICIENT_BUFFER:
|
|
||||||
+ raise RuntimeError(f"Failed to query token information buffer size! Error code: 0x{error_code:X}")
|
|
||||||
+ else:
|
|
||||||
+ raise RuntimeError("Unexpected return value from GetTokenInformation!")
|
|
||||||
+
|
|
||||||
+ # Allocate buffer
|
|
||||||
+ user_info = ctypes.create_string_buffer(user_info_size.value)
|
|
||||||
+ ret = advapi32.GetTokenInformation(
|
|
||||||
+ process_token,
|
|
||||||
+ TokenUser,
|
|
||||||
+ user_info,
|
|
||||||
+ user_info_size,
|
|
||||||
+ ctypes.byref(user_info_size),
|
|
||||||
+ )
|
|
||||||
+ if ret == 0:
|
|
||||||
+ error_code = kernel32.GetLastError()
|
|
||||||
+ raise RuntimeError(f"Failed to query token information! Error code: 0x{error_code:X}")
|
|
||||||
+
|
|
||||||
+ # Convert SID to string
|
|
||||||
+ # Technically, we need to pass user_info->User.Sid, but as they are at the beginning of the
|
|
||||||
+ # buffer, just pass the buffer instead...
|
|
||||||
+ sid_wstr = ctypes.wintypes.LPWSTR(None)
|
|
||||||
+ ret = advapi32.ConvertSidToStringSidW(
|
|
||||||
+ ctypes.cast(user_info, PTOKEN_USER).contents.User.Sid,
|
|
||||||
+ ctypes.pointer(sid_wstr),
|
|
||||||
+ )
|
|
||||||
+ if ret == 0:
|
|
||||||
+ error_code = kernel32.GetLastError()
|
|
||||||
+ raise RuntimeError(f"Failed to convert SID to string! Error code: 0x{error_code:X}")
|
|
||||||
+ sid = sid_wstr.value
|
|
||||||
+ kernel32.LocalFree(sid_wstr)
|
|
||||||
+ except Exception:
|
|
||||||
+ sid = None
|
|
||||||
+ finally:
|
|
||||||
+ # Close the process token
|
|
||||||
+ if process_token.value != INVALID_HANDLE:
|
|
||||||
+ kernel32.CloseHandle(process_token)
|
|
||||||
+
|
|
||||||
+ return sid
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+# Get and cache current user's SID
|
|
||||||
+_user_sid = _get_user_sid()
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def secure_mkdir(dir_name):
|
|
||||||
+ """
|
|
||||||
+ Replacement for mkdir that limits the access to created directory to current user.
|
|
||||||
+ """
|
|
||||||
+
|
|
||||||
+ # Create security descriptor
|
|
||||||
+ # Prefer actual user SID over SID S-1-3-4 (current owner), because at the time of writing, Wine does not properly
|
|
||||||
+ # support the latter.
|
|
||||||
+ sid = _user_sid or "S-1-3-4"
|
|
||||||
+
|
|
||||||
+ # DACL descriptor (D):
|
|
||||||
+ # ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;(resource_attribute)
|
|
||||||
+ # - ace_type = SDDL_ACCESS_ALLOWED (A)
|
|
||||||
+ # - rights = SDDL_FILE_ALL (FA)
|
|
||||||
+ # - account_sid = current user (queried SID)
|
|
||||||
+ security_desc_str = f"D:(A;;FA;;;{sid})"
|
|
||||||
+ security_desc = ctypes.wintypes.LPVOID(None)
|
|
||||||
+
|
|
||||||
+ ret = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
|
||||||
+ security_desc_str,
|
|
||||||
+ SDDL_REVISION1,
|
|
||||||
+ ctypes.byref(security_desc),
|
|
||||||
+ None,
|
|
||||||
+ )
|
|
||||||
+ if ret == 0:
|
|
||||||
+ error_code = kernel32.GetLastError()
|
|
||||||
+ raise RuntimeError(
|
|
||||||
+ f"Failed to create security descriptor! Error code: 0x{error_code:X}, "
|
|
||||||
+ f"message: {_win_error_to_message(error_code)}"
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ security_attr = SECURITY_ATTRIBUTES()
|
|
||||||
+ security_attr.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES)
|
|
||||||
+ security_attr.lpSecurityDescriptor = security_desc
|
|
||||||
+ security_attr.bInheritHandle = False
|
|
||||||
+
|
|
||||||
+ # Create directory
|
|
||||||
+ ret = kernel32.CreateDirectoryW(
|
|
||||||
+ dir_name,
|
|
||||||
+ security_attr,
|
|
||||||
+ )
|
|
||||||
+ if ret == 0:
|
|
||||||
+ # Call failed; store error code immediately, to avoid it being overwritten in cleanup below.
|
|
||||||
+ error_code = kernel32.GetLastError()
|
|
||||||
+
|
|
||||||
+ # Free security descriptor
|
|
||||||
+ kernel32.LocalFree(security_desc)
|
|
||||||
+
|
|
||||||
+ # Exit on succeess
|
|
||||||
+ if ret != 0:
|
|
||||||
+ return
|
|
||||||
+
|
|
||||||
+ # Construct OSError from win error code
|
|
||||||
+ error_message = _win_error_to_message(error_code)
|
|
||||||
+
|
|
||||||
+ # Strip trailing dot to match error message from os.mkdir().
|
|
||||||
+ if error_message and error_message[-1] == '.':
|
|
||||||
+ error_message = error_message[:-1]
|
|
||||||
+
|
|
||||||
+ raise OSError(
|
|
||||||
+ None, # errno
|
|
||||||
+ error_message, # strerror
|
|
||||||
+ dir_name, # filename
|
|
||||||
+ error_code, # winerror
|
|
||||||
+ None, # filename2
|
|
||||||
+ )
|
|
||||||
diff --git a/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py b/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..d035df0
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py
|
|
||||||
@@ -0,0 +1,25 @@
|
|
||||||
+# -----------------------------------------------------------------------------
|
|
||||||
+# Copyright (c) 2023, PyInstaller Development Team.
|
|
||||||
+#
|
|
||||||
+# Distributed under the terms of the GNU General Public License (version 2
|
|
||||||
+# or later) with exception for distributing the bootloader.
|
|
||||||
+#
|
|
||||||
+# The full license is in the file COPYING.txt, distributed with this software.
|
|
||||||
+#
|
|
||||||
+# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
|
|
||||||
+# -----------------------------------------------------------------------------
|
|
||||||
+"""
|
|
||||||
+This hook allows discovery and collection of PyInstaller's internal _pyi_rth_utils module that provides utility
|
|
||||||
+functions for run-time hooks.
|
|
||||||
+
|
|
||||||
+The module is implemented in 'PyInstaller/fake-modules/_pyi_rth_utils.py'.
|
|
||||||
+"""
|
|
||||||
+
|
|
||||||
+import os
|
|
||||||
+
|
|
||||||
+from PyInstaller import PACKAGEPATH
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+def pre_find_module_path(api):
|
|
||||||
+ module_dir = os.path.join(PACKAGEPATH, 'fake-modules')
|
|
||||||
+ api.search_dirs = [module_dir]
|
|
||||||
diff --git a/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py b/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py
|
|
||||||
index 018d6fe..6ea9425 100755
|
|
||||||
--- a/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py
|
|
||||||
+++ b/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py
|
|
||||||
@@ -27,10 +27,12 @@ def _pyi_rthook():
|
|
||||||
import atexit
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
- import tempfile
|
|
||||||
|
|
||||||
- # Put matplot config dir to temp directory.
|
|
||||||
- configdir = tempfile.mkdtemp()
|
|
||||||
+ import _pyi_rth_utils # PyInstaller's run-time hook utilities module
|
|
||||||
+
|
|
||||||
+ # Isolate matplotlib's config dir into temporary directory.
|
|
||||||
+ # Use our replacement for `tempfile.mkdtemp` function that properly restricts access to directory on all platforms.
|
|
||||||
+ configdir = _pyi_rth_utils.secure_mkdtemp()
|
|
||||||
os.environ['MPLCONFIGDIR'] = configdir
|
|
||||||
|
|
||||||
try:
|
|
||||||
diff --git a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py
|
|
||||||
index aed2515..a9bbbd1 100755
|
|
||||||
--- a/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py
|
|
||||||
+++ b/PyInstaller/hooks/rthooks/pyi_rth_win32comgenpy.py
|
|
||||||
@@ -21,13 +21,15 @@ def _pyi_rthook():
|
|
||||||
import atexit
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
- import tempfile
|
|
||||||
|
|
||||||
import win32com
|
|
||||||
|
|
||||||
- # Create temporary directory. The actual cache directory needs to be named `gen_py`, so create a sub-directory.
|
|
||||||
- supportdir = tempfile.mkdtemp()
|
|
||||||
+ import _pyi_rth_utils # PyInstaller's run-time hook utilities module
|
|
||||||
|
|
||||||
+ # Create temporary directory.
|
|
||||||
+ # Use our replacement for `tempfile.mkdtemp` function that properly restricts access to directory on all platforms.
|
|
||||||
+ supportdir = _pyi_rth_utils.secure_mkdtemp()
|
|
||||||
+ # The actual cache directory needs to be named `gen_py`, so create a sub-directory.
|
|
||||||
genpydir = os.path.join(supportdir, 'gen_py')
|
|
||||||
os.makedirs(genpydir, exist_ok=True)
|
|
||||||
|
|
||||||
diff --git a/news/7827.bugfix.rst b/news/7827.bugfix.rst
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..41ea37a
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/news/7827.bugfix.rst
|
|
||||||
@@ -0,0 +1,5 @@
|
|
||||||
+(Windows) Ensure that the access to temporary directories created by
|
|
||||||
+the ``matplotlib`` and ``win32com`` run-time hooks is restricted to
|
|
||||||
+the user running the frozen application, even if ``TMP`` / ``TEMP``
|
|
||||||
+environment directory points to a system-wide location that can be
|
|
||||||
+accessed to all users.
|
|
||||||
diff --git a/setup.cfg b/setup.cfg
|
|
||||||
index 7cd1548..756ae34 100755
|
|
||||||
--- a/setup.cfg
|
|
||||||
+++ b/setup.cfg
|
|
||||||
@@ -70,6 +70,7 @@ include =
|
|
||||||
PyInstaller =
|
|
||||||
bootloader/*/*
|
|
||||||
fake-modules/*.py
|
|
||||||
+ fake-modules/_pyi_rth_utils/*.py
|
|
||||||
hooks/rthooks.dat
|
|
||||||
lib/README.rst
|
|
||||||
|
|
||||||
diff --git a/setup.py b/setup.py
|
|
||||||
index 51d2482..ac82bb6 100755
|
|
||||||
--- a/setup.py
|
|
||||||
+++ b/setup.py
|
|
||||||
@@ -114,6 +114,7 @@ def finalize_options(self):
|
|
||||||
*(f"bootloader/images/*.{suffix}" for suffix in self.ICON_TYPES),
|
|
||||||
# These files need to be explicitly included as well.
|
|
||||||
"fake-modules/*.py",
|
|
||||||
+ "fake-modules/_pyi_rth_utils/*.py",
|
|
||||||
"hooks/rthooks.dat",
|
|
||||||
"lib/README.rst",
|
|
||||||
],
|
|
||||||
--
|
|
||||||
2.43.0
|
|
||||||
|
|
||||||
Binary file not shown.
@ -1,17 +1,15 @@
|
|||||||
%global _empty_manifest_terminate_build 0
|
%global _empty_manifest_terminate_build 0
|
||||||
Name: python-pyinstaller
|
Name: python-pyinstaller
|
||||||
Version: 5.13.0
|
Version: 3.6
|
||||||
Release: 2
|
Release: 1
|
||||||
Summary: PyInstaller bundles a Python application and all its dependencies into a single package.
|
Summary: PyInstaller bundles a Python application and all its dependencies into a single package.
|
||||||
License: GPL-2.0-only
|
License: GPL license with a special exception which allows to use PyInstaller to build and distribute non-free programs (including commercial ones)
|
||||||
URL: http://www.pyinstaller.org
|
URL: http://www.pyinstaller.org
|
||||||
Source0: https://files.pythonhosted.org/packages/51/37/2e0195ef4e4dec35e3f116361c4c780e0c4cd2cd96079199b3218c08fabb/pyinstaller-%{version}.tar.gz
|
Source0: https://files.pythonhosted.org/packages/3c/c9/c3f9bc64eb11eee6a824686deba6129884c8cbdf70e750661773b9865ee0/PyInstaller-3.6.tar.gz
|
||||||
# https://github.com/pyinstaller/pyinstaller/commit/709262381451878dadb9e9d26190167a2ab5e67c
|
Patch6000: Fix-Gcc-warnings-for-strncpy-and-strncat.patch
|
||||||
Patch3000: backport-CVE-2023-49797-pre.patch
|
Patch6001: Reimplement-pyi-search-path-using-strtok.patch
|
||||||
# https://github.com/pyinstaller/pyinstaller/commit/5a53dc58295b26eb8af1f146df990a657bc916d1
|
Patch6002: Use-snprintf-to-simplify-some-string-len.patch
|
||||||
Patch3001: backport-CVE-2023-49797.patch
|
|
||||||
BuildRequires: python3-devel python3-setuptools zlib-devel
|
BuildRequires: python3-devel python3-setuptools zlib-devel
|
||||||
BuildRequires: python3-wheel
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
PyInstaller bundles a Python application and all its dependencies into a single
|
PyInstaller bundles a Python application and all its dependencies into a single
|
||||||
@ -37,7 +35,7 @@ package. The user can run the packaged app without installing a Python
|
|||||||
interpreter or any modules.
|
interpreter or any modules.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%autosetup -n pyinstaller-%{version} -p1
|
%autosetup -n PyInstaller-%{version} -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%py3_build
|
%py3_build
|
||||||
@ -72,20 +70,10 @@ mv %{buildroot}/doclist.lst .
|
|||||||
|
|
||||||
%files -n python3-pyinstaller -f filelist.lst
|
%files -n python3-pyinstaller -f filelist.lst
|
||||||
%dir %{python3_sitelib}/*
|
%dir %{python3_sitelib}/*
|
||||||
%exclude %{python3_sitelib}/PyInstaller/bootloader/{D*,W*,*32*,Linux-64bit}
|
|
||||||
|
|
||||||
%files help -f doclist.lst
|
%files help -f doclist.lst
|
||||||
%{_pkgdocdir}
|
%{_pkgdocdir}
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Tue Jun 18 2024 yaoxin <yao_xin001@hoperun.com> - 5.13.0-2
|
|
||||||
- Fix CVE-2023-49797
|
|
||||||
|
|
||||||
* Mon Jul 10 2023 chenzixuan<chenzixuan@kylinos.cn> - 5.13.0-1
|
|
||||||
- Update to 5.13.0
|
|
||||||
|
|
||||||
* Tue May 16 2023 yaoxin <yao_xin001@hoperun.com> - 5.10.1-1
|
|
||||||
- Update to 5.10.1
|
|
||||||
|
|
||||||
* Mon Jun 22 2020 Python_Bot <Python_Bot@openeuler.org>
|
* Mon Jun 22 2020 Python_Bot <Python_Bot@openeuler.org>
|
||||||
- Package Spec generated
|
- Package Spec generated
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
version_control: pypi
|
|
||||||
src_repo: PyInstaller
|
|
||||||
tag_prefix: "v"
|
|
||||||
seperator: ""
|
|
||||||
Loading…
x
Reference in New Issue
Block a user