diff options
author | Pali Rohár <pali@kernel.org> | 2022-11-18 21:47:04 +0100 |
---|---|---|
committer | Pali Rohár <pali@kernel.org> | 2022-11-18 21:47:04 +0100 |
commit | 0382965825caa27deaac3ab6a25145c896b9053b (patch) | |
tree | e7eb354c31a350fdb9cf15e75c7441dd0ff5856f | |
parent | e2d9340ba416ef0856fb8198e16ffd255225952c (diff) | |
download | pciutils-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.c | 31 |
1 files changed, 26 insertions, 5 deletions
@@ -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); |