From 39a55920018ef19cc01b53063a2f090fe05d4982 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Thu, 12 Jun 2003 03:01:55 +0000 Subject: [PATCH] SF Patch #744104: Remove eval() from csv Eliminates the eval() step in the csv module resulting in better security, more clarity, and a little speed. The idea is to make successive attempts to coerce the string to a python type: int(s), long(s), float(s), etc. As a by-product, eliminates a bare 'except' statement. --- Lib/csv.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/Lib/csv.py b/Lib/csv.py index 83b8aa447de..851150218fc 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -148,6 +148,11 @@ class DictWriter: rows.append(self._dict_to_list(rowdict)) return self.writer.writerows(rows) +# Guard Sniffer's type checking against builds that exclude complex() +try: + complex +except NameError: + complex = float class Sniffer: ''' @@ -360,13 +365,6 @@ class Sniffer: # Finally, a 'vote' is taken at the end for each column, adding or # subtracting from the likelihood of the first row being a header. - def seval(item): - """ - Strips parens from item prior to calling eval in an - attempt to make it safer - """ - return eval(item.replace('(', '').replace(')', '')) - rdr = reader(StringIO(sample), self.sniff(sample)) header = rdr.next() # assume first row is header @@ -386,18 +384,21 @@ class Sniffer: continue # skip rows that have irregular number of columns for col in columnTypes.keys(): - try: + + for thisType in [int, long, float, complex]: try: - # is it a built-in type (besides string)? - thisType = type(seval(row[col])) - except OverflowError: - # a long int? - thisType = type(seval(row[col] + 'L')) - thisType = type(0) # treat long ints as int - except: + thisType(row[col]) + break + except ValueError, OverflowError: + pass + else: # fallback to length of string thisType = len(row[col]) + # treat longs as ints + if thisType == long: + thisType = int + if thisType != columnTypes[col]: if columnTypes[col] is None: # add new column type columnTypes[col] = thisType @@ -417,8 +418,8 @@ class Sniffer: hasHeader -= 1 else: # attempt typecast try: - eval("%s(%s)" % (colType.__name__, header[col])) - except: + colType(header[col]) + except ValueError, TypeError: hasHeader += 1 else: hasHeader -= 1