From e6698e4baa0017ed3d96647068274a5090cde175 Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Sat, 16 Nov 2013 14:39:50 +0100 Subject: [PATCH] Enforcing string start/end check. See #1687 --- .../app/preproc/PdePreprocessor.java | 61 ++++++++++++------- .../app/preproc/StringWithCcomment.ino | 4 ++ .../preproc/StringWithCcomment.stripped.ino | 4 ++ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/app/src/processing/app/preproc/PdePreprocessor.java b/app/src/processing/app/preproc/PdePreprocessor.java index 1f7c15966..89993c43f 100644 --- a/app/src/processing/app/preproc/PdePreprocessor.java +++ b/app/src/processing/app/preproc/PdePreprocessor.java @@ -49,7 +49,7 @@ public class PdePreprocessor { // stores number of included library headers written // we always write one header: Arduino.h public int headerCount = 1; - + // the prototypes that are generated by the preprocessor List prototypes; @@ -68,11 +68,11 @@ public class PdePreprocessor { /** * Setup a new preprocessor. */ - public PdePreprocessor() { + public PdePreprocessor() { } /** - * Writes out the head of the c++ code generated for a sketch. + * Writes out the head of the c++ code generated for a sketch. * Called from processing.app.Sketch. * @param program the concatenated code from all tabs containing pde-files */ @@ -115,7 +115,7 @@ public class PdePreprocessor { // store # of prototypes so that line number reporting can be adjusted prototypeCount = prototypes.size(); - + // do this after the program gets re-combobulated this.program = program; @@ -164,7 +164,7 @@ public class PdePreprocessor { /** * preprocesses a pde file and writes out a cpp file into the specified * OutputStream - * + * * @param output * @throws Exception */ @@ -177,10 +177,10 @@ public class PdePreprocessor { // Write the pde program to the cpp file protected void writeProgram(PrintStream out, String program, List prototypes) { int prototypeInsertionPoint = firstStatement(program); - + out.print(program.substring(0, prototypeInsertionPoint)); - out.print("#include \"Arduino.h\"\n"); - + out.print("#include \"Arduino.h\"\n"); + // print user defined prototypes for (int i = 0; i < prototypes.size(); i++) { out.print(prototypes.get(i) + "\n"); @@ -214,7 +214,7 @@ public class PdePreprocessor { public int firstStatement(String in) { // whitespace String p = "\\s+"; - + // multi-line and single-line comment //p += "|" + "(//\\s*?$)|(/\\*\\s*?\\*/)"; p += "|(/\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/)|(//.*?$)"; @@ -222,7 +222,7 @@ public class PdePreprocessor { // pre-processor directive p += "|(#(?:\\\\\\n|.)*)"; Pattern pattern = Pattern.compile(p, Pattern.MULTILINE); - + Matcher matcher = pattern.matcher(in); int i = 0; while (matcher.find()) { @@ -230,10 +230,10 @@ public class PdePreprocessor { break; i = matcher.end(); } - + return i; } - + /** * Strips comments, pre-processor directives, single- and double-quoted * strings from a string. @@ -271,7 +271,7 @@ public class PdePreprocessor { StringBuffer buffer = new StringBuffer(); int nesting = 0; int start = 0; - + // XXX: need to keep newlines inside braces so we can determine the line // number of a prototype for (int i = 0; i < in.length(); i++) { @@ -288,12 +288,12 @@ public class PdePreprocessor { } } } - + buffer.append(in.substring(start)); - + return buffer.toString(); } - + public ArrayList prototypes(String in) { in = collapseBraces(strip(in)); @@ -301,19 +301,19 @@ public class PdePreprocessor { // XXX: doesn't handle function pointers Pattern prototypePattern = Pattern.compile("[\\w\\[\\]\\*]+\\s+[&\\[\\]\\*\\w\\s]+\\([&,\\[\\]\\*\\w\\s]*\\)(?=\\s*;)"); Pattern functionPattern = Pattern.compile("[\\w\\[\\]\\*]+\\s+[&\\[\\]\\*\\w\\s]+\\([&,\\[\\]\\*\\w\\s]*\\)(?=\\s*\\{)"); - + // Find already declared prototypes ArrayList prototypeMatches = new ArrayList(); Matcher prototypeMatcher = prototypePattern.matcher(in); while (prototypeMatcher.find()) prototypeMatches.add(prototypeMatcher.group(0) + ";"); - + // Find all functions and generate prototypes for them ArrayList functionMatches = new ArrayList(); Matcher functionMatcher = functionPattern.matcher(in); while (functionMatcher.find()) functionMatches.add(functionMatcher.group(0) + ";"); - + // Remove generated prototypes that exactly match ones found in the source file for (int functionIndex=functionMatches.size() - 1; functionIndex >= 0; functionIndex--) { for (int prototypeIndex=0; prototypeIndex < prototypeMatches.size(); prototypeIndex++) { @@ -323,10 +323,29 @@ public class PdePreprocessor { } } } - + return functionMatches; } + private boolean isStartOrEndOfString(char p[], int index) { + if (p[index] != '\"') { + return false; + } + + if (index == 0) { + return true; + } + + if (p[index - 1] == '\\') { + return false; + } + + if (index - 2 >= 0 && p[index - 2] == '\\') { + return true; + } + + return true; + } /** * Replace all commented portions of a given String as spaces. @@ -338,7 +357,7 @@ public class PdePreprocessor { int index = 0; boolean insideString = false; while (index < p.length) { - if (p[index] == '\"') { + if (isStartOrEndOfString(p, index)) { insideString = !insideString; } // for any double slash comments, ignore until the end of the line diff --git a/app/test/processing/app/preproc/StringWithCcomment.ino b/app/test/processing/app/preproc/StringWithCcomment.ino index 675043f56..88b94e1d0 100644 --- a/app/test/processing/app/preproc/StringWithCcomment.ino +++ b/app/test/processing/app/preproc/StringWithCcomment.ino @@ -1,6 +1,10 @@ void setup() { // put your setup code here, to run once: + // "comment with a double quote + /* \" other comment with double quote */ Serial.println("Accept: */*"); + Serial.println("Accept: \" */*"); + Serial.println("Accept: \\"); // */*"); } void loop() { diff --git a/app/test/processing/app/preproc/StringWithCcomment.stripped.ino b/app/test/processing/app/preproc/StringWithCcomment.stripped.ino index 955aced29..60c701cdf 100644 --- a/app/test/processing/app/preproc/StringWithCcomment.stripped.ino +++ b/app/test/processing/app/preproc/StringWithCcomment.stripped.ino @@ -1,6 +1,10 @@ void setup() { + + Serial.println( ); + Serial.println( ); + Serial.println( ); } void loop() {