Selaa lähdekoodia

Merge pull request #2113 from thinkyhead/command_sanitizer

Command sanitizer
Scott Lahteine 10 vuotta sitten
vanhempi
commit
4d11b29959
1 muutettua tiedostoa jossa 118 lisäystä ja 122 poistoa
  1. 118
    122
      Marlin/Marlin_main.cpp

+ 118
- 122
Marlin/Marlin_main.cpp Näytä tiedosto

@@ -141,7 +141,7 @@
141 141
  * M112 - Emergency stop
142 142
  * M114 - Output current position to serial port
143 143
  * M115 - Capabilities string
144
- * M117 - display message
144
+ * M117 - Display a message on the controller screen
145 145
  * M119 - Output Endstop status to serial port
146 146
  * M120 - Enable endstop detection
147 147
  * M121 - Disable endstop detection
@@ -236,6 +236,7 @@ bool axis_known_position[3] = { false };
236 236
 
237 237
 static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
238 238
 
239
+static char *current_command, *current_command_args;
239 240
 static int cmd_queue_index_r = 0;
240 241
 static int cmd_queue_index_w = 0;
241 242
 static int commands_in_queue = 0;
@@ -265,7 +266,7 @@ static bool relative_mode = false;  //Determines Absolute or Relative Coordinate
265 266
 static char serial_char;
266 267
 static int serial_count = 0;
267 268
 static boolean comment_mode = false;
268
-static char *strchr_pointer; ///< A pointer to find chars in the command string (X, Y, Z, E, etc.)
269
+static char *seen_pointer; ///< A pointer to find chars in the command string (X, Y, Z, E, etc.)
269 270
 const char* queued_commands_P= NULL; /* pointer to the current line in the active sequence of commands, or NULL when none */
270 271
 const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
271 272
 // Inactivity shutdown
@@ -785,21 +786,20 @@ void get_command() {
785 786
         fromsd[cmd_queue_index_w] = false;
786 787
       #endif
787 788
 
788
-      if (strchr(command, 'N') != NULL) {
789
-        strchr_pointer = strchr(command, 'N');
790
-        gcode_N = (strtol(strchr_pointer + 1, NULL, 10));
789
+      char *npos = strchr(command, 'N');
790
+      char *apos = strchr(command, '*');
791
+      if (npos) {
792
+        gcode_N = strtol(npos + 1, NULL, 10);
791 793
         if (gcode_N != gcode_LastN + 1 && strstr_P(command, PSTR("M110")) == NULL) {
792 794
           gcode_line_error(PSTR(MSG_ERR_LINE_NO));
793 795
           return;
794 796
         }
795 797
 
796
-        if (strchr(command, '*') != NULL) {
797
-          byte checksum = 0;
798
-          byte count = 0;
798
+        if (apos) {
799
+          byte checksum = 0, count = 0;
799 800
           while (command[count] != '*') checksum ^= command[count++];
800
-          strchr_pointer = strchr(command, '*');
801 801
 
802
-          if (strtol(strchr_pointer + 1, NULL, 10) != checksum) {
802
+          if (strtol(apos + 1, NULL, 10) != checksum) {
803 803
             gcode_line_error(PSTR(MSG_ERR_CHECKSUM_MISMATCH));
804 804
             return;
805 805
           }
@@ -813,28 +813,26 @@ void get_command() {
813 813
         gcode_LastN = gcode_N;
814 814
         // if no errors, continue parsing
815 815
       }
816
-      else {  // if we don't receive 'N' but still see '*'
817
-        if ((strchr(command, '*') != NULL)) {
818
-          gcode_line_error(PSTR(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM), false);
819
-          return;
820
-        }
816
+      else if (apos) { // No '*' without 'N'
817
+        gcode_line_error(PSTR(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM), false);
818
+        return;
821 819
       }
822 820
 
823
-      if (strchr(command, 'G') != NULL) {
824
-        strchr_pointer = strchr(command, 'G');
825
-        switch (strtol(strchr_pointer + 1, NULL, 10)) {
826
-          case 0:
827
-          case 1:
828
-          case 2:
829
-          case 3:
830
-            if (IsStopped()) {
821
+      // Movement commands alert when stopped
822
+      if (IsStopped()) {
823
+        char *gpos = strchr(command, 'G');
824
+        if (gpos) {
825
+          int codenum = strtol(gpos + 1, NULL, 10);
826
+          switch (codenum) {
827
+            case 0:
828
+            case 1:
829
+            case 2:
830
+            case 3:
831 831
               SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
832 832
               LCD_MESSAGEPGM(MSG_STOPPED);
833
-            }
834
-            break;
835
-          default:
836
-            break;
837
-        }
833
+              break;
834
+          }
835
+        }        
838 836
       }
839 837
 
840 838
       // If command was e-stop process now
@@ -916,32 +914,32 @@ void get_command() {
916 914
 
917 915
 bool code_has_value() {
918 916
   int i = 1;
919
-  char c = strchr_pointer[i];
920
-  if (c == '-' || c == '+') c = strchr_pointer[++i];
921
-  if (c == '.') c = strchr_pointer[++i];
917
+  char c = seen_pointer[i];
918
+  if (c == '-' || c == '+') c = seen_pointer[++i];
919
+  if (c == '.') c = seen_pointer[++i];
922 920
   return (c >= '0' && c <= '9');
923 921
 }
924 922
 
925 923
 float code_value() {
926 924
   float ret;
927
-  char *e = strchr(strchr_pointer, 'E');
925
+  char *e = strchr(seen_pointer, 'E');
928 926
   if (e) {
929 927
     *e = 0;
930
-    ret = strtod(strchr_pointer+1, NULL);
928
+    ret = strtod(seen_pointer+1, NULL);
931 929
     *e = 'E';
932 930
   }
933 931
   else
934
-    ret = strtod(strchr_pointer+1, NULL);
932
+    ret = strtod(seen_pointer+1, NULL);
935 933
   return ret;
936 934
 }
937 935
 
938
-long code_value_long() { return strtol(strchr_pointer + 1, NULL, 10); }
936
+long code_value_long() { return strtol(seen_pointer + 1, NULL, 10); }
939 937
 
940
-int16_t code_value_short() { return (int16_t)strtol(strchr_pointer + 1, NULL, 10); }
938
+int16_t code_value_short() { return (int16_t)strtol(seen_pointer + 1, NULL, 10); }
941 939
 
942 940
 bool code_seen(char code) {
943
-  strchr_pointer = strchr(command_queue[cmd_queue_index_r], code);
944
-  return (strchr_pointer != NULL);  //Return True if a character was found
941
+  seen_pointer = strchr(current_command_args, code); // +3 since "G0 " is the shortest prefix
942
+  return (seen_pointer != NULL);  //Return True if a character was found
945 943
 }
946 944
 
947 945
 #define DEFINE_PGM_READ_ANY(type, reader)       \
@@ -1792,6 +1790,13 @@ void gcode_get_destination() {
1792 1790
   }
1793 1791
 }
1794 1792
 
1793
+void unknown_command_error() {
1794
+  SERIAL_ECHO_START;
1795
+  SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
1796
+  SERIAL_ECHO(current_command);
1797
+  SERIAL_ECHOPGM("\"\n");
1798
+}
1799
+
1795 1800
 /**
1796 1801
  * G0, G1: Coordinated movement of X Y Z E axes
1797 1802
  */
@@ -2843,7 +2848,7 @@ inline void gcode_G92() {
2843 2848
    * M1: // M1 - Conditional stop - Wait for user button press on LCD
2844 2849
    */
2845 2850
   inline void gcode_M0_M1() {
2846
-    char *src = strchr_pointer + 2;
2851
+    char *args = current_command_args;
2847 2852
 
2848 2853
     millis_t codenum = 0;
2849 2854
     bool hasP = false, hasS = false;
@@ -2855,11 +2860,9 @@ inline void gcode_G92() {
2855 2860
       codenum = code_value() * 1000; // seconds to wait
2856 2861
       hasS = codenum > 0;
2857 2862
     }
2858
-    char* starpos = strchr(src, '*');
2859
-    if (starpos != NULL) *(starpos) = '\0';
2860
-    while (*src == ' ') ++src;
2861
-    if (!hasP && !hasS && *src != '\0')
2862
-      lcd_setstatus(src, true);
2863
+
2864
+    if (!hasP && !hasS && *args != '\0')
2865
+      lcd_setstatus(args, true);
2863 2866
     else {
2864 2867
       LCD_MESSAGEPGM(MSG_USERWAIT);
2865 2868
       #if defined(LCD_PROGRESS_BAR) && PROGRESS_MSG_EXPIRE > 0
@@ -2932,10 +2935,7 @@ inline void gcode_M17() {
2932 2935
    * M23: Select a file
2933 2936
    */
2934 2937
   inline void gcode_M23() {
2935
-    char* codepos = strchr_pointer + 4;
2936
-    char* starpos = strchr(codepos, '*');
2937
-    if (starpos) *starpos = '\0';
2938
-    card.openFile(codepos, true);
2938
+    card.openFile(current_command_args, true);
2939 2939
   }
2940 2940
 
2941 2941
   /**
@@ -2972,14 +2972,7 @@ inline void gcode_M17() {
2972 2972
    * M28: Start SD Write
2973 2973
    */
2974 2974
   inline void gcode_M28() {
2975
-    char* codepos = strchr_pointer + 4;
2976
-    char* starpos = strchr(codepos, '*');
2977
-    if (starpos) {
2978
-      char* npos = strchr(command_queue[cmd_queue_index_r], 'N');
2979
-      strchr_pointer = strchr(npos, ' ') + 1;
2980
-      *(starpos) = '\0';
2981
-    }
2982
-    card.openFile(codepos, false);
2975
+    card.openFile(current_command_args, false);
2983 2976
   }
2984 2977
 
2985 2978
   /**
@@ -2996,13 +2989,7 @@ inline void gcode_M17() {
2996 2989
   inline void gcode_M30() {
2997 2990
     if (card.cardOK) {
2998 2991
       card.closefile();
2999
-      char* starpos = strchr(strchr_pointer + 4, '*');
3000
-      if (starpos) {
3001
-        char* npos = strchr(command_queue[cmd_queue_index_r], 'N');
3002
-        strchr_pointer = strchr(npos, ' ') + 1;
3003
-        *(starpos) = '\0';
3004
-      }
3005
-      card.removeFile(strchr_pointer + 4);
2992
+      card.removeFile(current_command_args);
3006 2993
     }
3007 2994
   }
3008 2995
 
@@ -3032,23 +3019,18 @@ inline void gcode_M31() {
3032 3019
     if (card.sdprinting)
3033 3020
       st_synchronize();
3034 3021
 
3035
-    char* codepos = strchr_pointer + 4;
3036
-
3037
-    char* namestartpos = strchr(codepos, '!');   //find ! to indicate filename string start.
3038
-    if (! namestartpos)
3039
-      namestartpos = codepos; //default name position, 4 letters after the M
3022
+    char* namestartpos = strchr(current_command_args, '!');  // Find ! to indicate filename string start.
3023
+    if (!namestartpos)
3024
+      namestartpos = current_command_args; // Default name position, 4 letters after the M
3040 3025
     else
3041 3026
       namestartpos++; //to skip the '!'
3042 3027
 
3043
-    char* starpos = strchr(codepos, '*');
3044
-    if (starpos) *(starpos) = '\0';
3045
-
3046
-    bool call_procedure = code_seen('P') && (strchr_pointer < namestartpos);
3028
+    bool call_procedure = code_seen('P') && (seen_pointer < namestartpos);
3047 3029
 
3048 3030
     if (card.cardOK) {
3049 3031
       card.openFile(namestartpos, true, !call_procedure);
3050 3032
 
3051
-      if (code_seen('S') && strchr_pointer < namestartpos) // "S" (must occur _before_ the filename!)
3033
+      if (code_seen('S') && seen_pointer < namestartpos) // "S" (must occur _before_ the filename!)
3052 3034
         card.setIndex(code_value_short());
3053 3035
 
3054 3036
       card.startFileprint();
@@ -3061,13 +3043,7 @@ inline void gcode_M31() {
3061 3043
    * M928: Start SD Write
3062 3044
    */
3063 3045
   inline void gcode_M928() {
3064
-    char* starpos = strchr(strchr_pointer + 5, '*');
3065
-    if (starpos) {
3066
-      char* npos = strchr(command_queue[cmd_queue_index_r], 'N');
3067
-      strchr_pointer = strchr(npos, ' ') + 1;
3068
-      *(starpos) = '\0';
3069
-    }
3070
-    card.openLogFile(strchr_pointer + 5);
3046
+    card.openLogFile(current_command_args);
3071 3047
   }
3072 3048
 
3073 3049
 #endif // SDSUPPORT
@@ -3864,16 +3840,12 @@ inline void gcode_M115() {
3864 3840
   SERIAL_PROTOCOLPGM(MSG_M115_REPORT);
3865 3841
 }
3866 3842
 
3867
-#ifdef ULTIPANEL
3868
-
3869
-  /**
3870
-   * M117: Set LCD Status Message
3871
-   */
3872
-  inline void gcode_M117() {
3873
-    lcd_setstatus(strchr_pointer + 5);
3874
-  }
3875
-
3876
-#endif
3843
+/**
3844
+ * M117: Set LCD Status Message
3845
+ */
3846
+inline void gcode_M117() {
3847
+  lcd_setstatus(current_command_args);
3848
+}
3877 3849
 
3878 3850
 /**
3879 3851
  * M119: Output endstop states to serial output
@@ -4161,10 +4133,7 @@ inline void gcode_M206() {
4161 4133
           autoretract_enabled = true;
4162 4134
           break;
4163 4135
         default:
4164
-          SERIAL_ECHO_START;
4165
-          SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
4166
-          SERIAL_ECHO(command_queue[cmd_queue_index_r]);
4167
-          SERIAL_ECHOLNPGM("\"");
4136
+          unknown_command_error();
4168 4137
           return;
4169 4138
       }
4170 4139
       for (int i=0; i<EXTRUDERS; i++) retracted[i] = false;
@@ -5084,8 +5053,7 @@ inline void gcode_M999() {
5084 5053
  *
5085 5054
  *   F[mm/min] Set the movement feedrate
5086 5055
  */
5087
-inline void gcode_T() {
5088
-  uint16_t tmp_extruder = code_value_short();
5056
+inline void gcode_T(uint8_t tmp_extruder) {
5089 5057
   if (tmp_extruder >= EXTRUDERS) {
5090 5058
     SERIAL_ECHO_START;
5091 5059
     SERIAL_CHAR('T');
@@ -5188,21 +5156,52 @@ inline void gcode_T() {
5188 5156
 }
5189 5157
 
5190 5158
 /**
5191
- * Process Commands and dispatch them to handlers
5159
+ * Process a single command and dispatch it to its handler
5192 5160
  * This is called from the main loop()
5193 5161
  */
5194 5162
 void process_next_command() {
5163
+  current_command = command_queue[cmd_queue_index_r];
5195 5164
 
5196 5165
   if ((marlin_debug_flags & DEBUG_ECHO)) {
5197 5166
     SERIAL_ECHO_START;
5198
-    SERIAL_ECHOLN(command_queue[cmd_queue_index_r]);
5167
+    SERIAL_ECHOLN(current_command);
5168
+  }
5169
+
5170
+  // Sanitize the current command:
5171
+  //  - Skip leading spaces
5172
+  //  - Bypass N...
5173
+  //  - Overwrite * with nul to mark the end
5174
+  while (*current_command == ' ') ++current_command;
5175
+  if (*current_command == 'N' && current_command[1] >= '0' && current_command[1] <= '9') {
5176
+    while (*current_command != ' ') ++current_command;
5177
+    while (*current_command == ' ') ++current_command;
5199 5178
   }
5179
+  char *starpos = strchr(current_command, '*');  // * should always be the last parameter
5180
+  if (starpos) *starpos = '\0';
5181
+
5182
+  // Get the command code, which must be G, M, or T
5183
+  char command_code = *current_command;
5184
+
5185
+  // The code must have a numeric value
5186
+  bool code_is_good = (current_command[1] >= '0' && current_command[1] <= '9');
5187
+
5188
+  int codenum; // define ahead of goto
5200 5189
 
5201
-  if (code_seen('G')) {
5190
+  // Bail early if there's no code
5191
+  if (!code_is_good) goto ExitUnknownCommand;
5202 5192
 
5203
-    int codenum = code_value_short();
5193
+  // Args pointer optimizes code_seen, especially those taking XYZEF
5194
+  // This wastes a little cpu on commands that expect no arguments.
5195
+  current_command_args = current_command;
5196
+  while (*current_command_args != ' ') ++current_command_args;
5197
+  while (*current_command_args == ' ') ++current_command_args;
5204 5198
 
5205
-    switch (codenum) {
5199
+  // Interpret the code int
5200
+  codenum = code_value_short();
5201
+
5202
+  // Handle a known G, M, or T
5203
+  switch(command_code) {
5204
+    case 'G': switch (codenum) {
5206 5205
 
5207 5206
     // G0, G1
5208 5207
     case 0:
@@ -5271,11 +5270,12 @@ void process_next_command() {
5271 5270
     case 92: // G92
5272 5271
       gcode_G92();
5273 5272
       break;
5273
+
5274
+    default: code_is_good = false;
5274 5275
     }
5275
-  }
5276
+    break;
5276 5277
 
5277
-  else if (code_seen('M')) {
5278
-    switch(code_value_short()) {
5278
+    case 'M': switch (codenum) {
5279 5279
       #ifdef ULTIPANEL
5280 5280
         case 0: // M0 - Unconditional stop - Wait for user button press on LCD
5281 5281
         case 1: // M1 - Conditional stop - Wait for user button press on LCD
@@ -5350,8 +5350,7 @@ void process_next_command() {
5350 5350
 
5351 5351
       case 105: // M105: Read current temperature
5352 5352
         gcode_M105();
5353
-        return;
5354
-        break;
5353
+        return; // "ok" already printed
5355 5354
 
5356 5355
       case 109: // M109: Wait for temperature
5357 5356
         gcode_M109();
@@ -5425,13 +5424,9 @@ void process_next_command() {
5425 5424
       case 115: // M115: Report capabilities
5426 5425
         gcode_M115();
5427 5426
         break;
5428
-
5429
-      #ifdef ULTIPANEL
5430
-        case 117: // M117: Set LCD message text
5431
-          gcode_M117();
5432
-          break;
5433
-      #endif
5434
-
5427
+      case 117: // M117: Set LCD message text, if possible
5428
+        gcode_M117();
5429
+        break;
5435 5430
       case 114: // M114: Report current position
5436 5431
         gcode_M114();
5437 5432
         break;
@@ -5701,19 +5696,20 @@ void process_next_command() {
5701 5696
       case 999: // M999: Restart after being Stopped
5702 5697
         gcode_M999();
5703 5698
         break;
5699
+
5700
+      default: code_is_good = false;
5704 5701
     }
5705
-  }
5702
+    break;
5706 5703
 
5707
-  else if (code_seen('T')) {
5708
-    gcode_T();
5704
+    case 'T':
5705
+      gcode_T(codenum);
5706
+    break;
5709 5707
   }
5710 5708
 
5711
-  else {
5712
-    SERIAL_ECHO_START;
5713
-    SERIAL_ECHOPGM(MSG_UNKNOWN_COMMAND);
5714
-    SERIAL_ECHO(command_queue[cmd_queue_index_r]);
5715
-    SERIAL_ECHOLNPGM("\"");
5716
-  }
5709
+ExitUnknownCommand:
5710
+
5711
+  // Still unknown command? Throw an error
5712
+  if (!code_is_good) unknown_command_error();
5717 5713
 
5718 5714
   ok_to_send();
5719 5715
 }

Loading…
Peruuta
Tallenna