public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: "Martin Storsjö" <martin@martin.st>
To: binutils@sourceware.org
Subject: [PATCH v6] ld: Make archive member file extension comparisons case insensitive when cross compiling too
Date: Wed, 24 Aug 2022 13:47:47 +0300	[thread overview]
Message-ID: <20220824104747.11804-1-martin@martin.st> (raw)
In-Reply-To: <9b767c3b-2690-863c-e7dd-17fa477ee482@martin.st>

On Windows, filename_cmp is case insensitive, but when cross compiling
with libraries that may contain members with uppercase file names, we
should keep those comparisons case insensitive when running the build
tools on other OSes too.

Also make the check for .def consistent with the other ones, fixing
out of bounds reads if file names are shorter than 4 characters.
---
v6: Switch the check for .def extension to use strrchr, add a missed
null pointer check at the third call site.
---
 ld/emultempl/pe.em  | 32 +++++++++++++++++++++++++++-----
 ld/emultempl/pep.em | 32 +++++++++++++++++++++++++++-----
 2 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index ad969ccec13..03c261e89c6 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -534,6 +534,28 @@ gld${EMULATION_NAME}_list_options (FILE *file)
   fprintf (file, _("  --build-id[=STYLE]                 Generate build ID\n"));
 }
 
+/* A case insensitive comparison, regardless of the host platform, used for
+   comparing file extensions. Parameter s1 points at the extension in a file
+   name (pointing at the starting '.'). Parameter s2 is a lower case string
+   without the leading '.'.  */
+static int
+fileext_cmp (const char *s1, const char *s2)
+{
+  if (*s1 != '.')
+    return 1;
+  s1++;
+  for (;;)
+    {
+      int c1 = TOLOWER (*s1++);
+      int c2 = *s2++; /* Assumed to be lower case from the caller.  */
+
+      if (c1 != c2)
+        return (c1 - c2);
+
+      if (c1 == '\0')
+        return 0;
+    }
+}
 
 static void
 set_pe_name (char *name, long val)
@@ -1666,7 +1688,7 @@ gld${EMULATION_NAME}_after_open (void)
 		       extension, and use that for the remainder of the
 		       comparisons.  */
 		    pnt = strrchr (bfd_get_filename (is3->the_bfd), '.');
-		    if (pnt != NULL && filename_cmp (pnt, ".dll") == 0)
+		    if (pnt != NULL && fileext_cmp (pnt, "dll") == 0)
 		      break;
 		  }
 
@@ -1683,7 +1705,7 @@ gld${EMULATION_NAME}_after_open (void)
 			/* Skip static members, ie anything with a .obj
 			   extension.  */
 			pnt = strrchr (bfd_get_filename (is2->the_bfd), '.');
-			if (pnt != NULL && filename_cmp (pnt, ".obj") == 0)
+			if (pnt != NULL && fileext_cmp (pnt, "obj") == 0)
 			  continue;
 
 			if (filename_cmp (bfd_get_filename (is3->the_bfd),
@@ -1701,7 +1723,7 @@ gld${EMULATION_NAME}_after_open (void)
 	       then leave the filename alone.  */
 	    pnt = strrchr (bfd_get_filename (is->the_bfd), '.');
 
-	    if (is_ms_arch && (filename_cmp (pnt, ".dll") == 0))
+	    if (is_ms_arch && pnt != NULL && (fileext_cmp (pnt, "dll") == 0))
 	      {
 		int idata2 = 0, reloc_count=0;
 		asection *sec;
@@ -1855,9 +1877,9 @@ static bool
 gld${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
 {
 #ifdef DLL_SUPPORT
-  const char *ext = entry->filename + strlen (entry->filename) - 4;
+  const char *ext = strrchr (entry->filename, '.');
 
-  if (filename_cmp (ext, ".def") == 0 || filename_cmp (ext, ".DEF") == 0)
+  if (ext != NULL && fileext_cmp (ext, "def") == 0)
     {
       pe_def_file = def_file_parse (entry->filename, pe_def_file);
 
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index ee36a9a7e56..239f830edbb 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -181,6 +181,28 @@ static int is_underscoring (void)
   return pep_leading_underscore;
 }
 
+/* A case insensitive comparison, regardless of the host platform, used for
+   comparing file extensions. Parameter s1 points at the extension in a file
+   name (pointing at the starting '.'). Parameter s2 is a lower case string
+   without the leading '.'.  */
+static int
+fileext_cmp (const char *s1, const char *s2)
+{
+  if (*s1 != '.')
+    return 1;
+  s1++;
+  for (;;)
+    {
+      int c1 = TOLOWER (*s1++);
+      int c2 = *s2++; /* Assumed to be lower case from the caller.  */
+
+      if (c1 != c2)
+        return (c1 - c2);
+
+      if (c1 == '\0')
+        return 0;
+    }
+}
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -1630,7 +1652,7 @@ gld${EMULATION_NAME}_after_open (void)
 		       extension, and use that for the remainder of the
 		       comparisons.  */
 		    pnt = strrchr (bfd_get_filename (is3->the_bfd), '.');
-		    if (pnt != NULL && filename_cmp (pnt, ".dll") == 0)
+		    if (pnt != NULL && fileext_cmp (pnt, "dll") == 0)
 		      break;
 		  }
 
@@ -1647,7 +1669,7 @@ gld${EMULATION_NAME}_after_open (void)
 			/* Skip static members, ie anything with a .obj
 			   extension.  */
 			pnt = strrchr (bfd_get_filename (is2->the_bfd), '.');
-			if (pnt != NULL && filename_cmp (pnt, ".obj") == 0)
+			if (pnt != NULL && fileext_cmp (pnt, "obj") == 0)
 			  continue;
 
 			if (filename_cmp (bfd_get_filename (is3->the_bfd),
@@ -1665,7 +1687,7 @@ gld${EMULATION_NAME}_after_open (void)
 	       then leave the filename alone.  */
 	    pnt = strrchr (bfd_get_filename (is->the_bfd), '.');
 
-	    if (is_ms_arch && (filename_cmp (pnt, ".dll") == 0))
+	    if (is_ms_arch && pnt != NULL && (fileext_cmp (pnt, "dll") == 0))
 	      {
 		int idata2 = 0, reloc_count=0;
 		asection *sec;
@@ -1725,9 +1747,9 @@ static bool
 gld${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
 {
 #ifdef DLL_SUPPORT
-  const char *ext = entry->filename + strlen (entry->filename) - 4;
+  const char *ext = strrchr (entry->filename, '.');
 
-  if (filename_cmp (ext, ".def") == 0 || filename_cmp (ext, ".DEF") == 0)
+  if (ext != NULL && fileext_cmp (ext, "def") == 0)
     {
       pep_def_file = def_file_parse (entry->filename, pep_def_file);
 
-- 
2.25.1


  parent reply	other threads:[~2022-08-24 10:47 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-23 13:06 [PATCH v2] ld: Make library member file suffix " Martin Storsjö
2022-08-23 14:01 ` Nick Clifton
2022-08-23 14:19   ` Martin Storsjö
2022-08-23 14:23   ` Jan Beulich
2022-08-23 21:11     ` [PATCH v3] ld: Make archive member file extension " Martin Storsjö
2022-08-24  6:38       ` Jan Beulich
2022-08-24  8:23         ` [PATCH v4] " Martin Storsjö
2022-08-24  9:48           ` Nick Clifton
2022-08-24 10:03             ` Martin Storsjö
2022-08-24 10:04               ` [PATCH v5] " Martin Storsjö
2022-08-24 10:29                 ` Jan Beulich
2022-08-24 10:46                   ` Martin Storsjö
2022-08-24 10:46                     ` Martin Storsjö
2022-08-24 10:47                     ` Martin Storsjö [this message]
2022-08-24 11:17                       ` [PATCH v6] " Jan Beulich
2022-08-24 12:25                         ` [PATCH v7] " Martin Storsjö
2022-08-24 12:39                           ` Jan Beulich
2022-08-24 12:56                           ` Nick Clifton
2022-08-24 20:23                             ` Martin Storsjö
2022-08-25  6:53             ` [PATCH v4] " Martin Storsjö

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220824104747.11804-1-martin@martin.st \
    --to=martin@martin.st \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).