From 5dbeb128d9d33ef23e15b65dad1c7cc28793692d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 17 Sep 2012 05:15:36 +0000 Subject: [PATCH] compile: Detect invalid and likely-bad import statements. * Make-lang.in (go/gogo.o): Depend on filenames.h. From-SVN: r191372 --- gcc/go/ChangeLog | 4 +++ gcc/go/Make-lang.in | 9 ++++--- gcc/go/gofrontend/gogo.cc | 53 ++++++++++++++++++++++++++++++++++++++ gcc/go/gofrontend/lex.cc | 30 +++++++++++++++++++++ gcc/go/gofrontend/lex.h | 4 +++ gcc/go/gofrontend/parse.cc | 3 ++- 6 files changed, 98 insertions(+), 5 deletions(-) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index d3a6e29a9ec..18a9aa663f9 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,7 @@ +2012-09-16 Ian Lance Taylor + + * Make-lang.in (go/gogo.o): Depend on filenames.h. + 2012-08-14 Diego Novillo Merge from cxx-conversion branch. Configury. diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in index 34e5584cc09..b3cb2bdbc19 100644 --- a/gcc/go/Make-lang.in +++ b/gcc/go/Make-lang.in @@ -289,10 +289,11 @@ go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \ 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) \ diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 6e9b8c124aa..a434c4df6bb 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -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 @@ Gogo::import_package(const std::string& filename, 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 --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc index 5b7ce6869e6..42d444b5fbc 100644 --- a/gcc/go/gofrontend/lex.cc +++ b/gcc/go/gofrontend/lex.cc @@ -1705,6 +1705,27 @@ struct Unicode_range 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 @@ Lex::is_in_unicode_range(unsigned int c, const Unicode_range* ranges, } } +// 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 --git a/gcc/go/gofrontend/lex.h b/gcc/go/gofrontend/lex.h index 8858e73d97a..074bbaea4ed 100644 --- a/gcc/go/gofrontend/lex.h +++ b/gcc/go/gofrontend/lex.h @@ -375,6 +375,10 @@ class Lex 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 --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index 29323f05c6c..cfcc00f99ee 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -5337,7 +5337,8 @@ Parse::import_spec(void*) 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; }