Fix lexing regression in certain types of method parameter lists

It was mis-lexing the case when a class descriptor is immediately
followed by a primitive type. The primitive type was being lexed as
PARAM_LIST_OR_ID_PRIMITIVE_TYPE instead of PRIMITIVE_TYPE.

The root cause was due to an incorrect state change. Since the
CLASS_DESCRIPTOR state can be started from within the PARAM_LIST state,
but when the CLASS_DESCRIPTOR state ends it just went back to YYINITIAL,
instead of going back to PARAM_LIST.

This adds a state stack to track these state changes
This commit is contained in:
Ben Gruver 2019-09-19 13:46:33 -07:00
parent 2598dff4b1
commit ae2efe146b
5 changed files with 37 additions and 4 deletions

View File

@ -1,6 +1,7 @@
package org.jf.smali;
import java.io.*;
import java.util.Stack;
import org.antlr.runtime.*;
import org.jf.smali.util.*;
import org.jf.util.*;
@ -38,6 +39,8 @@ import static org.jf.smali.smaliParser.*;
private int apiLevel;
private Stack<Integer> stateStack = new Stack<>();
public Token nextToken() {
try {
Token token = yylex();
@ -137,6 +140,7 @@ import static org.jf.smali.smaliParser.*;
}
private void beginStateBasedToken(int state) {
stateStack.push(yystate());
yybegin(state);
sb.setLength(0);
tokenStartLine = getLine();
@ -146,12 +150,12 @@ import static org.jf.smali.smaliParser.*;
}
private Token endStateBasedToken(int type) {
yybegin(YYINITIAL);
if (tokenError != null) {
return invalidStateBasedToken(tokenError);
}
yybegin(stateStack.pop());
CommonToken token = new CommonToken(type, sb.toString());
token.setStartIndex(tokenStartChar);
token.setStopIndex(yychar + yylength() - 1);
@ -167,7 +171,7 @@ import static org.jf.smali.smaliParser.*;
}
private Token invalidStateBasedToken(String message) {
yybegin(YYINITIAL);
yybegin(stateStack.pop());
InvalidToken token = new InvalidToken(message, sb.toString());
token.setStartIndex(tokenStartChar);
@ -734,7 +738,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
{ClassDescriptor} {
yypushback(yylength());
beginStateBasedToken(CLASS_DESCRIPTOR_BEGINNING);
sb.append(yytext());
}
// we have to drop into a separate state so that we don't parse something like

View File

@ -37,6 +37,7 @@ IIIII
ZBSCIJFD
ILa;[La;[I
Ljava/lang/String;Ljava/lang/String;
IIFFIILjava/lang/String;IIFFII
[I[I[I
[I[Z
[I[Ljava/lang/String;

View File

@ -73,6 +73,20 @@ PRIMITIVE_TYPE("I")
CLASS_DESCRIPTOR("Ljava/lang/String;")
CLASS_DESCRIPTOR("Ljava/lang/String;")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
CLASS_DESCRIPTOR("Ljava/lang/String;")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")

View File

@ -37,6 +37,7 @@ IIIII
ZBSCIJFD
ILa;[La;[I
Ljava/lang/String;Ljava/lang/String;
IIFFIILjava/lang/String;IIFFII
[I[I[I
[I[Z
[I[Ljava/lang/String;

View File

@ -73,6 +73,20 @@ PRIMITIVE_TYPE("I")
CLASS_DESCRIPTOR("Ljava/lang/String;")
CLASS_DESCRIPTOR("Ljava/lang/String;")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
CLASS_DESCRIPTOR("Ljava/lang/String;")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("F")
PRIMITIVE_TYPE("I")
PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")
PRIMITIVE_TYPE("I")
ARRAY_TYPE_PREFIX("[")