Patchwork Go patch committed: Detect invalid import statements

login
register
mail settings
Submitter Ian Taylor
Date Sept. 17, 2012, 5:15 a.m.
Message ID <mcripbdp6uw.fsf@google.com>
Download mbox | patch
Permalink /patch/184284/
State New
Headers show

Comments

Ian Taylor - Sept. 17, 2012, 5:15 a.m.
This patch to the Go compiler checks for invalid import filenames,
including checks for cases that are technically valid but likely to be
wrong.  This corresponds to the tests done by the gc Go compiler.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.  Will commit to 4.7 branch when it is open again.

Ian


2012-09-16  Ian Lance Taylor  <iant@google.com>

	* Make-lang.in (go/gogo.o): Depend on filenames.h.

Patch

diff -r 773bab2333b6 go/gogo.cc
--- a/go/gogo.cc	Mon Sep 10 21:59:01 2012 -0700
+++ b/go/gogo.cc	Sun Sep 16 22:05:25 2012 -0700
@@ -6,6 +6,8 @@ 
 
 #include "go-system.h"
 
+#include "filenames.h"
+
 #include "go-c.h"
 #include "go-dump.h"
 #include "lex.h"
@@ -385,6 +387,57 @@ 
 		     bool is_local_name_exported,
 		     Location location)
 {
+  if (filename.empty())
+    {
+      error_at(location, "import path is empty");
+      return;
+    }
+
+  const char *pf = filename.data();
+  const char *pend = pf + filename.length();
+  while (pf < pend)
+    {
+      unsigned int c;
+      int adv = Lex::fetch_char(pf, &c);
+      if (adv == 0)
+	{
+	  error_at(location, "import path contains invalid UTF-8 sequence");
+	  return;
+	}
+      if (c == '\0')
+	{
+	  error_at(location, "import path contains NUL");
+	  return;
+	}
+      if (c < 0x20 || c == 0x7f)
+	{
+	  error_at(location, "import path contains control character");
+	  return;
+	}
+      if (c == '\\')
+	{
+	  error_at(location, "import path contains backslash; use slash");
+	  return;
+	}
+      if (Lex::is_unicode_space(c))
+	{
+	  error_at(location, "import path contains space character");
+	  return;
+	}
+      if (c < 0x7f && strchr("!\"#$%&'()*,:;<=>?[]^`{|}", c) != NULL)
+	{
+	  error_at(location, "import path contains invalid character '%c'", c);
+	  return;
+	}
+      pf += adv;
+    }
+
+  if (IS_ABSOLUTE_PATH(filename.c_str()))
+    {
+      error_at(location, "import path cannot be absolute path");
+      return;
+    }
+
   if (filename == "unsafe")
     {
       this->import_unsafe(local_name, is_local_name_exported, location);
diff -r 773bab2333b6 go/lex.cc
--- a/go/lex.cc	Mon Sep 10 21:59:01 2012 -0700
+++ b/go/lex.cc	Sun Sep 16 22:05:25 2012 -0700
@@ -1705,6 +1705,27 @@ 
   unsigned int stride;
 };
 
+// A table of whitespace characters--Unicode code points classified as
+// "Space", "C" locale whitespace characters, the "next line" control
+// character (0085), the line separator (2028), the paragraph
+// separator (2029), and the "zero-width non-break space" (feff).
+
+static const Unicode_range unicode_space[] =
+{
+  { 0x0009, 0x000d, 1 },
+  { 0x0020, 0x0020, 1 },
+  { 0x0085, 0x0085, 1 },
+  { 0x00a0, 0x00a0, 1 },
+  { 0x1680, 0x1680, 1 },
+  { 0x180e, 0x180e, 1 },
+  { 0x2000, 0x200a, 1 },
+  { 0x2028, 0x2029, 1 },
+  { 0x202f, 0x202f, 1 },
+  { 0x205f, 0x205f, 1 },
+  { 0x3000, 0x3000, 1 },
+  { 0xfeff, 0xfeff, 1 },
+};
+
 // A table of Unicode digits--Unicode code points classified as
 // "Digit".
 
@@ -2294,6 +2315,15 @@ 
     }
 }
 
+// Return whether C is a space character.
+
+bool
+Lex::is_unicode_space(unsigned int c)
+{
+  return Lex::is_in_unicode_range(c, unicode_space,
+				  ARRAY_SIZE(unicode_space));
+}
+
 // Return whether C is a Unicode digit--a Unicode code point
 // classified as "Digit".
 
diff -r 773bab2333b6 go/lex.h
--- a/go/lex.h	Mon Sep 10 21:59:01 2012 -0700
+++ b/go/lex.h	Sun Sep 16 22:05:25 2012 -0700
@@ -375,6 +375,10 @@ 
   static int
   fetch_char(const char* str, unsigned int *value);
 
+  // Return whether C is a Unicode or "C" locale space character.
+  static bool
+  is_unicode_space(unsigned int c);
+
  private:
   ssize_t
   get_line();
diff -r 773bab2333b6 go/parse.cc
--- a/go/parse.cc	Mon Sep 10 21:59:01 2012 -0700
+++ b/go/parse.cc	Sun Sep 16 22:05:25 2012 -0700
@@ -5337,7 +5337,8 @@ 
 
   if (!token->is_string())
     {
-      error_at(this->location(), "missing import package name");
+      error_at(this->location(), "import statement not a string");
+      this->advance_token();
       return;
     }
 
Index: gcc/go/Make-lang.in
===================================================================
--- gcc/go/Make-lang.in	(revision 191279)
+++ gcc/go/Make-lang.in	(working copy)
@@ -289,10 +289,11 @@  go/gogo-tree.o: go/gofrontend/gogo-tree.
 	convert.h output.h $(DIAGNOSTIC_H) $(GO_TYPES_H) \
 	$(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_RUNTIME_H) \
 	go/gofrontend/backend.h $(GO_GOGO_H)
-go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \
-	go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \
-	$(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_RUNTIME_H) \
-	$(GO_IMPORT_H) $(GO_EXPORT_H) go/gofrontend/backend.h $(GO_GOGO_H)
+go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) \
+	$(srcdir)/../include/filenames.h $(GO_C_H) go/gofrontend/go-dump.h \
+	$(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) \
+	go/gofrontend/dataflow.h $(GO_RUNTIME_H) $(GO_IMPORT_H) \
+	$(GO_EXPORT_H) go/gofrontend/backend.h $(GO_GOGO_H)
 go/import.o: go/gofrontend/import.cc $(GO_SYSTEM_H) \
 	$(srcdir)/../include/filenames.h $(srcdir)/../include/simple-object.h \
 	$(GO_C_H) $(GO_GOGO_H) $(GO_LEX_H) $(GO_TYPES_H) $(GO_EXPORT_H) \