1
0
mirror of https://github.com/golang/go synced 2024-11-25 11:07:59 -07:00

gc: reject import paths containing special characters

Also allow multiple invalid import statements in a
single file.

Fixes #3021. The changes to go/parser and the
language specifcation have already been committed.

R=rsc, gri
CC=golang-dev
https://golang.org/cl/5672084
This commit is contained in:
Anthony Martin 2012-02-24 14:48:36 -05:00 committed by Russ Cox
parent 490c3d4a42
commit dc38756ce1
8 changed files with 2106 additions and 1957 deletions

View File

@ -1171,6 +1171,7 @@ Type* getthisx(Type *t);
int implements(Type *t, Type *iface, Type **missing, Type **have, int *ptr);
void importdot(Pkg *opkg, Node *pack);
int is64(Type *t);
int isbadimport(Strlit *s);
int isblank(Node *n);
int isblanksym(Sym *s);
int isfixedarray(Type *t);

View File

@ -205,7 +205,15 @@ import_stmt:
my->lastlineno = $1;
my->block = 1; // at top level
}
| import_here import_there
{
// When an invalid import path is passed to importfile,
// it calls yyerror and then sets up a fake import with
// no package statement. This allows us to test more
// than one invalid import statement in a single file.
if(nerrors == 0)
fatal("phase error in import");
}
import_stmt_list:
import_stmt

View File

@ -573,6 +573,13 @@ findpkg(Strlit *name)
return 0;
}
static void
fakeimport(void)
{
importpkg = mkpkg(strlit("fake"));
cannedimports("fake.6", "$$\n");
}
void
importfile(Val *f, int line)
{
@ -589,17 +596,19 @@ importfile(Val *f, int line)
if(f->ctype != CTSTR) {
yyerror("import statement not a string");
fakeimport();
return;
}
if(strlen(f->u.sval->s) != f->u.sval->len) {
yyerror("import path contains NUL");
errorexit();
if(f->u.sval->len == 0) {
yyerror("import path is empty");
fakeimport();
return;
}
if(strchr(f->u.sval->s, '\\')) {
yyerror("import path contains backslash; use slash");
errorexit();
if(isbadimport(f->u.sval)) {
fakeimport();
return;
}
// The package name main is no longer reserved,

View File

@ -3560,10 +3560,8 @@ mkpkg(Strlit *path)
Pkg *p;
int h;
if(strlen(path->s) != path->len) {
yyerror("import path contains NUL byte");
if(isbadimport(path))
errorexit();
}
h = stringhash(path->s) & (nelem(phash)-1);
for(p=phash[h]; p; p=p->link)
@ -3612,3 +3610,41 @@ addinit(Node **np, NodeList *init)
n->ninit = concat(init, n->ninit);
n->ullman = UINF;
}
int
isbadimport(Strlit *path)
{
char *s;
Rune r;
if(strlen(path->s) != path->len) {
yyerror("import path contains NUL");
return 1;
}
s = path->s;
while(*s) {
s += chartorune(&r, s);
if(r == Runeerror) {
yyerror("import path contains invalid UTF-8 sequence");
return 1;
}
if(r < 0x20 || r == 0x7f) {
yyerror("import path contains control character");
return 1;
}
if(r == '\\') {
yyerror("import path contains backslash; use slash");
return 1;
}
if(isspacerune(r)) {
yyerror("import path contains space character");
return 1;
}
if(utfrune("!\"#$%&'()*,:;<=>?[]^`{|}~", r)) {
yyerror("import path contains invalid character '%C'", r);
return 1;
}
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,8 @@
/* A Bison parser, made by GNU Bison 2.5. */
/* A Bison parser, made by GNU Bison 2.4.1. */
/* Bison interface for Yacc-like parsers in C
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -148,7 +146,7 @@
typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
/* Line 2068 of yacc.c */
#line 28 "go.y"
Node* node;
@ -160,8 +158,8 @@ typedef union YYSTYPE
/* Line 1676 of yacc.c */
#line 165 "y.tab.h"
/* Line 2068 of yacc.c */
#line 163 "y.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */

View File

@ -14,25 +14,25 @@ static struct {
// is converted by bisonerrors into the yystate and yychar caused
// by that token list.
220, ',',
221, ',',
"unexpected comma during import block",
376, ';',
377, ';',
"unexpected semicolon or newline before {",
397, ';',
398, ';',
"unexpected semicolon or newline before {",
236, ';',
237, ';',
"unexpected semicolon or newline before {",
473, LBODY,
474, LBODY,
"unexpected semicolon or newline before {",
22, '{',
"unexpected semicolon or newline before {",
143, ';',
144, ';',
"unexpected semicolon or newline in type declaration",
37, '}',
@ -44,30 +44,30 @@ static struct {
37, ',',
"unexpected comma in channel type",
436, LELSE,
437, LELSE,
"unexpected semicolon or newline before else",
256, ',',
257, ',',
"name list not allowed in interface type",
236, LVAR,
237, LVAR,
"var declaration not allowed in for initializer",
65, '{',
"unexpected { at end of statement",
375, '{',
376, '{',
"unexpected { at end of statement",
124, ';',
125, ';',
"argument to go/defer must be function call",
424, ';',
425, ';',
"need trailing comma before newline in composite literal",
111, LNAME,
112, LNAME,
"nested func not allowed",
614, ';',
615, ';',
"else must be followed by if or statement block"
};

View File

@ -4,10 +4,48 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Verify that imports with backslashes are rejected by the compiler.
// Verify that invalid imports are rejected by the compiler.
// Does not compile.
// TODO: make more thorough.
package main
import `net\http` // ERROR "backslash"
// Correct import paths.
import _ "fmt"
import _ `time`
import _ "m\x61th"
import _ "go/parser"
// Correct import paths, but the packages don't exist.
// Don't test.
//import "a.b"
//import "greek/αβ"
// Import paths must be strings.
import 42 // ERROR "import statement"
import 'a' // ERROR "import statement"
import 3.14 // ERROR "import statement"
import 0.25i // ERROR "import statement"
// Each of these pairs tests both `` vs "" strings
// and also use of invalid characters spelled out as
// escape sequences and written directly.
// For example `"\x00"` tests import "\x00"
// while "`\x00`" tests import `<actual-NUL-byte>`.
import "" // ERROR "import path"
import `` // ERROR "import path"
import "\x00" // ERROR "import path"
import `\x00` // ERROR "import path"
import "\x7f" // ERROR "import path"
import `\x7f` // ERROR "import path"
import "a!" // ERROR "import path"
import `a!` // ERROR "import path"
import "a b" // ERROR "import path"
import `a b` // ERROR "import path"
import "a\\b" // ERROR "import path"
import `a\\b` // ERROR "import path"
import "\"`a`\"" // ERROR "import path"
import `\"a\"` // ERROR "import path"
import "\x80\x80" // ERROR "import path"
import `\x80\x80` // ERROR "import path"
import "\xFFFD" // ERROR "import path"
import `\xFFFD` // ERROR "import path"