Skip to content

Commit

Permalink
Prevent buffer overflow, loss of commands in run_gcode_script
Browse files Browse the repository at this point in the history
by using do_print which provides checksum, threading, ok waiting.
Use adapted GCoder which does not preload data, but accumulates it till the end
  • Loading branch information
volconst committed Jun 19, 2019
1 parent 6091f27 commit a214c2f
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 5 deletions.
2 changes: 2 additions & 0 deletions printrun/gcoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ def prepare(self, data = None, home_pos = None, layer_callback = None):
self.layer_idxs = array('I', [])
self.line_idxs = array('I', [])

def has_index(self, i):
return i < len(self)
def __len__(self):
return len(self.line_idxs)

Expand Down
4 changes: 2 additions & 2 deletions printrun/printcore.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ def _sendnext(self):
self._send(self.priqueue.get_nowait())
self.priqueue.task_done()
return
if self.printing and self.queueindex < len(self.mainqueue):
if self.printing and self.mainqueue.has_index(self.queueindex):
(layer, line) = self.mainqueue.idxs(self.queueindex)
gline = self.mainqueue.all_layers[layer][line]
if self.queueindex > 0:
Expand All @@ -604,7 +604,7 @@ def _sendnext(self):
try: handler.on_preprintsend(gline, self.queueindex, self.mainqueue)
except: logging.error(traceback.format_exc())
if self.preprintsendcb:
if self.queueindex + 1 < len(self.mainqueue):
if self.mainqueue.has_index(self.queueindex + 1):
(next_layer, next_line) = self.mainqueue.idxs(self.queueindex + 1)
next_gline = self.mainqueue.all_layers[next_layer][next_line]
else:
Expand Down
39 changes: 36 additions & 3 deletions printrun/pronsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,37 @@ def bed_enabled(self):
def extruder_enabled(self):
return self.extruder_temp != 0

class RGSGCoder():
"""Bare alternative to gcoder.LightGCode which does not preload all lines in memory,
but still allows run_gcode_script (hence the RGS) to be processed by do_print (checksum,threading,ok waiting)"""
def __init__(self, line):
self.lines = True
self.filament_length = 0.
self.filament_length_multi = [0]
self.proc = run_command(line, {"$s": 'str(self.filename)'}, stdout = subprocess.PIPE, universal_newlines = True)
lr = gcoder.Layer([])
lr.duration = 0.
self.all_layers = [lr]
self.read() #empty layer causes division by zero during progress calculation
def read(self):
ln = self.proc.stdout.readline()
if not ln:
self.proc.stdout.close()
return None
ln = ln.strip()
if not ln:
return None
pyLn = gcoder.PyLightLine(ln)
self.all_layers[0].append(pyLn)
return pyLn
def has_index(self, i):
while i >= len(self.all_layers[0]) and not self.proc.stdout.closed:
self.read()
return i < len(self.all_layers[0])
def __len__(self):
return len(self.all_layers[0])
def idxs(self, i):
return 0, i #layer, line

class pronsole(cmd.Cmd):
def __init__(self):
Expand Down Expand Up @@ -1755,9 +1786,11 @@ def help_run_script(self):
self.log(_("Runs a custom script. Current gcode filename can be given using $s token."))

def do_run_gcode_script(self, l):
p = run_command(l, {"$s": str(self.filename)}, stdout = subprocess.PIPE, universal_newlines = True)
for line in p.stdout.readlines():
self.onecmd(line.strip())
try:
self.fgcode = RGSGCoder(l)
self.do_print(None)
except BaseException as e:
self.logError(traceback.format_exc())

def help_run_gcode_script(self):
self.log(_("Runs a custom script which output gcode which will in turn be executed. Current gcode filename can be given using $s token."))
Expand Down
9 changes: 9 additions & 0 deletions testtools/lengthy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/python3
#generate many g1 to test serial buffer overflow in run_gcode_script

print('G28 X')
print('G1 X0')
for x in range(100):
print()
print(' ')
print('G1 X', x)

0 comments on commit a214c2f

Please sign in to comment.