GP-2809 Parse multiline string macro parameters used in WDM.h

This commit is contained in:
emteere 2023-05-03 20:12:39 +00:00
parent 0085e15971
commit a70c2129cd
4 changed files with 100 additions and 23 deletions

View file

@ -29,6 +29,8 @@ import ghidra.util.Msg;
public class DefineTable {
private static final String VARARG_ELLIPSIS = "...";
// the macro substitution could be done on a very large string, not just
// a single line, Don't want it to go out of control replacing things
private static final int ARBITRARY_MAX_REPLACEMENTS = 900000;
// Hastable for storing #defs
@ -274,22 +276,32 @@ public class DefineTable {
* @param pos position within string to start expanding
* @return string with all substitutions applied
*/
private String macroSub(String image, int pos, ArrayList<String> sublist) {
private String macroSub(String image, int pos, ArrayList<String> initialList) {
int replaceCount = 0;
StringBuffer buf = new StringBuffer(image);
int lastReplPos = pos;
boolean initialListSupplied = initialList != null; // initial list passed in
ArrayList<String> sublist = new ArrayList<String>();
if (initialList != null) {
sublist.addAll(initialList);
}
// don't replace an infinite number of times. Fail safe for possible ininite loop
while (pos < buf.length() && replaceCount < ARBITRARY_MAX_REPLACEMENTS) {
// clear list of used macros when move past replacement area
if (pos == lastReplPos) {
sublist = new ArrayList<String>(); // ok to clear list of used macro names
if (initialList != null) {
sublist.addAll(initialList); // add back in initialList of nonreplacement names
}
}
String defName = getDefineAt(buf, pos);
if (shouldReplace(buf, defName, pos)) {
// stop recursion on the same replacement string
int replPos = replace(buf, defName, pos, sublist);
int replPos = replace(buf, defName, pos, sublist, initialListSupplied);
if (replPos == -1) {
// if no replacement string, move on
@ -341,7 +353,7 @@ public class DefineTable {
return true;
}
int replace(StringBuffer buf, String currKey, int fromIndex, ArrayList<String> sublist) {
int replace(StringBuffer buf, String currKey, int fromIndex, ArrayList<String> sublist, boolean initialList) {
String replacementString = null;
if (sublist == null) {
@ -375,7 +387,9 @@ public class DefineTable {
Vector<PPToken> argv = getArgs(currKey);
int replacedSubpieceLen = currKey.length();
if (argv == null && sublist.contains(currKey)) {
System.err.println("DONT Replace " + currKey + " in: " + buf);
if (!initialList) {
System.err.println("DONT Replace " + currKey + " in: " + buf);
}
return -1;
}
if (argv != null) {
@ -613,7 +627,20 @@ public class DefineTable {
* @return
*/
public String expand(String image, boolean join) {
image = macroSub(image, 0, null);
return expand(image, join, null);
}
/**
* do the final expansion of "##" concats in the define strings that protect normal macro substitution.
*
* @param image
* @param join
* @param list of defines not to re-replace, stops recursive replacement on a define
* @return
*/
public String expand(String image, boolean join, ArrayList<String> list) {
image = macroSub(image, 0, list);
// get rid of ## constructs
if (join) {
@ -760,7 +787,11 @@ public class DefineTable {
// check if this is a numeric expression that could be simplified
//
String strValue = getValue(defName);
String strExpanded = expand(strValue, true);
ArrayList<String> list = new ArrayList();
list.add(defName);
String strExpanded = expand(strValue, true, list);
strValue = strExpanded;
return strValue;

View file

@ -828,6 +828,13 @@ public class PreProcessor {
println("False");
return false;
}
void bufAppendWithComment(PPToken buf, Token u) {
if (emitExecSwitch==true)
buf.append(u.image,true);
else
buf.append("//// " + u.image, false);
}
// Parse include file
private void includeFile(PPToken inc, boolean xsym) throws ParseException {
@ -1863,23 +1870,28 @@ PPToken Text() :
{Token u, nl, t = new Token(); PPToken buf = new PPToken(""); t.image="";}
{
( LOOKAHEAD(3)
(LOOKAHEAD(2)(u=<OUTER_TEXT>{ if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }
(LOOKAHEAD(2)nl=NewLines(){if (emitExecSwitch==true) buf.append(nl.image,true); else buf.append((u.image.length() == 0 ? "//// " : "") + nl.image, false); } )* |
(LOOKAHEAD(2)(u=<OUTER_TEXT>{ bufAppendWithComment(buf,u); }
(LOOKAHEAD(2)nl=NewLines() {if (emitExecSwitch==true) buf.append(nl.image,true); else buf.append((u.image.length() == 0 ? "//// " : "") + nl.image, false); } )* |
u=<OTHER_TEXT>{if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); } )
[LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }]
[LOOKAHEAD(2)u=QuotedText(){if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false);}]
[LOOKAHEAD(2)u=<OTHER_TEXT>{if (emitExecSwitch==true) buf.append(u.image, true); else buf.append("//// " + u.image, false); }
(LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image, true); else buf.append("//// " + u.image, false);})*])+|
u=<OTHER_TEXT> {bufAppendWithComment(buf,u); } )
[LOOKAHEAD(2)u=NewLines() {bufAppendWithComment(buf,u); }]
[(LOOKAHEAD(2)(u=QuotedText() {bufAppendWithComment(buf,u); }
[LOOKAHEAD(2)u=NewLines(){ bufAppendWithComment(buf,u); }] |
u=<OTHER_TEXT> {bufAppendWithComment(buf,u); })
[LOOKAHEAD(2)t=NewLines() {if (emitExecSwitch==true) buf.append(t.image,true); else buf.append("//// " + u.image, false); }]
[LOOKAHEAD(2)u=<OTHER_TEXT> {bufAppendWithComment(buf,u); }]
[LOOKAHEAD(2)u=NewLines() {bufAppendWithComment(buf,u); }])+]
[LOOKAHEAD(2)u=<OTHER_TEXT> {bufAppendWithComment(buf,u); }
(LOOKAHEAD(2)u=NewLines(){ bufAppendWithComment(buf,u);})*])+|
(LOOKAHEAD(2)(u=QuotedText(){if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }
[LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }]|
u=<OTHER_TEXT>{if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); })
[LOOKAHEAD(2)t=NewLines(){ if (emitExecSwitch==true) buf.append(t.image,true); else buf.append("//// " + u.image, false); }]
[LOOKAHEAD(2)u=<OTHER_TEXT>{if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }]
[LOOKAHEAD(2)u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }])+ |
(LOOKAHEAD(2)(u=QuotedText() {bufAppendWithComment(buf,u); }
[LOOKAHEAD(2)u=NewLines(){ bufAppendWithComment(buf,u); }] |
u=<OTHER_TEXT> {bufAppendWithComment(buf,u); })
[LOOKAHEAD(2)t=NewLines() {if (emitExecSwitch==true) buf.append(t.image,true); else buf.append("//// " + u.image, false); }]
[LOOKAHEAD(2)u=<OTHER_TEXT> {bufAppendWithComment(buf,u); }]
[LOOKAHEAD(2)u=NewLines() {bufAppendWithComment(buf,u); }])+ |
u=NewLines(){ if (emitExecSwitch==true) buf.append(u.image,true); else buf.append("//// " + u.image, false); }
u=NewLines() {bufAppendWithComment(buf,u); }
) { return buf;}
}
@ -1907,10 +1919,19 @@ PPToken NewLines() :
}
PPToken QuotedText() :
{Token u;}
{Token t = null; Token r = null; }
{
(u=<QUOTED_TEXT>)
{return new PPToken(u);}
(t=<QUOTED_TEXT>
{
if (r == null) {
r = t;
} else {
r.image = r.image.substring(0,r.image.length()) + t.image.substring(1);
}
}
)+
{ return new PPToken(r); }
}

View file

@ -117,6 +117,16 @@ public class PreProcessorTest extends AbstractGenericTest {
assertTrue("Expanded protected macro with args", results.contains("int (getc)(FILE * );"));
assertTrue("Expanded protected macro with args", results.contains("int (getchar)(void);"));
assertTrue("multi line string macro args failed ", results
.indexOf("0x1 = multi_line_worked(\"Some text first line\"\n" +
"\"More text second line\")") != -1);
assertTrue("multi line string macro args failed ", results
.indexOf("D = dual_line_worked(2,\"Caution: First line\"\n" +
"\" second line\"\n" +
"\" third line\"\n" +
"\" fourth line\")") != -1);
}
@Test

View file

@ -498,5 +498,20 @@ int does_not_has_include();
#define BEGINC QUOTED('"')
#define TEST_QUOTED_QUOTE QUOTED('"')
#define TEST_MULTILINE_TEXT(t) multi_line_worked(t)
A = TEST_MULTILINE_TEXT("One Line")
B = TEST_MULTILINE_TEXT("Some text first line"
"More text second line")
#define DUAL_MULTILINE(A, B) dual_line_worked(A,B)
C = DUAL_MULTILINE(1, OneLine("Caution: One Line"))
D = DUAL_MULTILINE(2, "Caution: First line"
" second line"
" third line"
" fourth line")
theEnd();