]> mj.ucw.cz Git - pciutils.git/commitdiff
libpci: windows: Fix usage of GetModuleFileName()
authorPali Rohár <pali@kernel.org>
Fri, 18 Nov 2022 20:47:04 +0000 (21:47 +0100)
committerPali Rohár <pali@kernel.org>
Fri, 18 Nov 2022 20:47:04 +0000 (21:47 +0100)
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.

lib/init.c

index e6efb8b2ab6b8cbeb841d15ba98bbf6d5de93114..9cb64f378a8c0ae644d41399293151c3a33cd454 100644 (file)
@@ -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);