summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2022-11-18 21:47:04 +0100
committerPali Rohár <pali@kernel.org>2022-11-18 21:47:04 +0100
commit0382965825caa27deaac3ab6a25145c896b9053b (patch)
treee7eb354c31a350fdb9cf15e75c7441dd0ff5856f
parente2d9340ba416ef0856fb8198e16ffd255225952c (diff)
downloadpciutils-0382965825caa27deaac3ab6a25145c896b9053b.tar.gz
libpci: windows: Fix usage of GetModuleFileName()
Module file name can have arbitrary length despite all MS examples say about MAX_PATH upper limit. This limit does not apply for example when executable is running from network disk with very long UNC paths or when using "\\??\\" prefix for specifying executable binary path. So handle buffer truncatenation by retrying GetModuleFileName() call with larger buffer. Fixes loading of pci.ids file when lspci.exe binary is running from network drive with path longer than 260 bytes.
-rw-r--r--lib/init.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/lib/init.c b/lib/init.c
index e6efb8b..9cb64f3 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -223,12 +223,33 @@ pci_init_name_list_path(struct pci_access *a)
else
{
char *path, *sep;
- DWORD len;
+ size_t len;
+ size_t size;
+
+ /*
+ * Module file name can have arbitrary length despite all MS examples say
+ * about MAX_PATH upper limit. This limit does not apply for example when
+ * executable is running from network disk with very long UNC paths or
+ * when using "\\??\\" prefix for specifying executable binary path.
+ * Function GetModuleFileName() returns passed size argument when passed
+ * buffer is too small and does not signal any error. In this case retry
+ * again with larger buffer.
+ */
+ size = 256; /* initial buffer size (more than sizeof(PCI_IDS)) */
+retry:
+ path = pci_malloc(a, size);
+ len = GetModuleFileNameA(module, path, size-sizeof(PCI_IDS));
+ if (len >= size-sizeof(PCI_IDS))
+ {
+ free(path);
+ size *= 2;
+ goto retry;
+ }
+ else if (len == 0)
+ path[0] = '\0';
- path = pci_malloc(a, MAX_PATH+1);
- len = GetModuleFileNameA(NULL, path, MAX_PATH+1);
- sep = (len > 0) ? strrchr(path, '\\') : NULL;
- if (len == 0 || len == MAX_PATH+1 || !sep || MAX_PATH-(size_t)(sep+1-path) < sizeof(PCI_IDS))
+ sep = strrchr(path, '\\');
+ if (!sep)
{
free(path);
pci_set_name_list_path(a, PCI_IDS, 0);