diff --git a/smali/src/main/java/org/jf/smali/Smali.java b/smali/src/main/java/org/jf/smali/Smali.java index 1c7d1584..855092ac 100644 --- a/smali/src/main/java/org/jf/smali/Smali.java +++ b/smali/src/main/java/org/jf/smali/Smali.java @@ -153,7 +153,7 @@ public class Smali { fis = new FileInputStream(smaliFile); InputStreamReader reader = new InputStreamReader(fis, "UTF-8"); - LexerErrorInterface lexer = new smaliFlexLexer(reader); + LexerErrorInterface lexer = new smaliFlexLexer(reader, options.apiLevel); ((smaliFlexLexer)lexer).setSourceFile(smaliFile); CommonTokenStream tokens = new CommonTokenStream((TokenSource)lexer); diff --git a/smali/src/main/java/org/jf/smali/SmaliTestUtils.java b/smali/src/main/java/org/jf/smali/SmaliTestUtils.java index 8b1d34a1..4aaecd96 100644 --- a/smali/src/main/java/org/jf/smali/SmaliTestUtils.java +++ b/smali/src/main/java/org/jf/smali/SmaliTestUtils.java @@ -61,7 +61,7 @@ public class SmaliTestUtils { Reader reader = new StringReader(smaliText); - lexer = new smaliFlexLexer(reader); + lexer = new smaliFlexLexer(reader, apiLevel); tokens = new CommonTokenStream((TokenSource)lexer); smaliParser parser = new smaliParser(tokens); diff --git a/smali/src/main/jflex/smaliLexer.jflex b/smali/src/main/jflex/smaliLexer.jflex index 4d0b5456..7b19d3dc 100644 --- a/smali/src/main/jflex/smaliLexer.jflex +++ b/smali/src/main/jflex/smaliLexer.jflex @@ -18,6 +18,11 @@ import static org.jf.smali.smaliParser.*; %column %char +%ctorarg int apiLevel +%init{ + this.apiLevel = apiLevel; +%init} + %{ private StringBuffer sb = new StringBuffer(); private String stringOrCharError = null; @@ -31,6 +36,8 @@ import static org.jf.smali.smaliParser.*; private boolean suppressErrors; + private int apiLevel; + public Token nextToken() { try { Token token = yylex(); @@ -129,6 +136,13 @@ import static org.jf.smali.smaliParser.*; return invalidToken(message, yytext()); } + private Token simpleNameToken(String text, boolean quoted) { + if (quoted) { + text = text.substring(1, text.length() - 1); /* strip backticks */ + } + return newToken(SIMPLE_NAME, text); + } + private void beginStringOrChar(int state) { yybegin(state); sb.setLength(0); @@ -228,8 +242,9 @@ SimpleNameCharacter = ({HighSurrogate} {LowSurrogate}) | [A-Za-z0-9$\-_\u00a1-\u UnicodeSpace = [\u0020\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000] /* Zs category */ SimpleNameRaw = {SimpleNameCharacter}+ -SimpleNameQuoted = [`] ({SimpleNameCharacter} | {UnicodeSpace})+ [`] -SimpleName = {SimpleNameRaw} | {SimpleNameQuoted} +SimpleNameQuoted = [`] {SimpleNameCharacter}+ [`] +SimpleNameQuotedWithSpaces = [`] ({SimpleNameCharacter} | {UnicodeSpace})+ [`] +SimpleName = {SimpleNameRaw} | {SimpleNameQuoted} | {SimpleNameQuotedWithSpaces} PrimitiveType = [ZBSCIJFD] @@ -685,11 +700,14 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | yybegin(PARAM_LIST); } - {SimpleNameRaw} { return newToken(SIMPLE_NAME); } - {SimpleNameQuoted} { - String quoted = yytext(); - String raw = quoted.substring(1, quoted.length() - 1); /* strip backticks */ - return newToken(SIMPLE_NAME, raw); + {SimpleNameRaw} { return simpleNameToken(yytext(), false); } + {SimpleNameQuoted} { return simpleNameToken(yytext(), true); } + {SimpleNameQuotedWithSpaces} { + if (apiLevel < 30) { + String message = "spaces in SimpleName are not allowed prior to API level 30"; + return new InvalidToken(message, yytext()); + } + return simpleNameToken(yytext(), true); } "<" {SimpleNameRaw} ">" { return newToken(MEMBER_NAME); } } diff --git a/smali/src/test/java/org/jf/smali/LexerTest.java b/smali/src/test/java/org/jf/smali/LexerTest.java index 5f1f21e4..bb886c9b 100644 --- a/smali/src/test/java/org/jf/smali/LexerTest.java +++ b/smali/src/test/java/org/jf/smali/LexerTest.java @@ -158,7 +158,8 @@ public class LexerTest { if (smaliStream == null) { Assert.fail("Could not load " + smaliFile); } - smaliFlexLexer lexer = new smaliFlexLexer(new InputStreamReader(smaliStream)); + smaliFlexLexer lexer = new smaliFlexLexer(new InputStreamReader(smaliStream), + 10000 /* most recent API level */); lexer.setSourceFile(new File(test + ".smali")); lexer.setSuppressErrors(true); diff --git a/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.smali b/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.smali index 2c0a6374..bde031ba 100644 --- a/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.smali +++ b/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.smali @@ -55,4 +55,5 @@ III [I->clone()Ljava/lang/Object; -`method_with_spaces_20 a0 1680 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 200a 202f 205f 3000 ` +`simple_name_in_backticks` +`simple_name_with_spaces_20 a0 1680 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 200a 202f 205f 3000 ` diff --git a/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.tokens b/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.tokens index 1652ab98..f53e0800 100644 --- a/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.tokens +++ b/smali/src/test/resources/LexerTest/TypeAndIdentifierTest.tokens @@ -109,4 +109,5 @@ OPEN_PAREN("(") CLOSE_PAREN(")") CLASS_DESCRIPTOR("Ljava/lang/Object;") -SIMPLE_NAME("method_with_spaces_20 a0 1680 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 200a 202f 205f 3000 ") +SIMPLE_NAME("simple_name_in_backticks") +SIMPLE_NAME("simple_name_with_spaces_20 a0 1680 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 200a 202f 205f 3000 ")