BF: binding parameter error (unsupported type) by writing json with invalid encoded lines into sqlite database (gh-973);

especially python < 3.0; try to prevent occurring such errors in the future;
pull/975/head
sebres 2015-02-25 11:54:46 +01:00
parent 50cbd4e9eb
commit 6c788a32ee
4 changed files with 43 additions and 12 deletions

View File

@ -38,6 +38,8 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released
system authentication issues system authentication issues
* fail2ban-regex reads filter file(s) completely, incl. '.local' file etc. (gh-954) * fail2ban-regex reads filter file(s) completely, incl. '.local' file etc. (gh-954)
* firewallcmd-* actions: split output into separate lines for grepping (gh-908) * firewallcmd-* actions: split output into separate lines for grepping (gh-908)
* binding parameter error (unsupported type) by writing json with invalid encoded
lines into sqlite database (gh-973), thanks to kot for issue reporting;
- New Features: - New Features:
- New filters: - New filters:

View File

@ -37,17 +37,35 @@ from ..helpers import getLogger
logSys = getLogger(__name__) logSys = getLogger(__name__)
if sys.version_info >= (3,): if sys.version_info >= (3,):
sqlite3.register_adapter( def _json_dumps_safe(x):
dict, try:
lambda x: json.dumps(x, ensure_ascii=False).encode( x = json.dumps(x, ensure_ascii=False).encode(
locale.getpreferredencoding(), 'replace')) locale.getpreferredencoding(), 'replace')
sqlite3.register_converter( except Exception, e: # pragma: no cover
"JSON", logSys.error('json dumps failed: %s', e)
lambda x: json.loads(x.decode( x = '{}'
locale.getpreferredencoding(), 'replace'))) return x
else: else:
sqlite3.register_adapter(dict, json.dumps) def _json_dumps_safe(x):
sqlite3.register_converter("JSON", json.loads) try:
x = json.dumps(x, ensure_ascii=False).decode(
locale.getpreferredencoding(), 'replace')
except Exception, e: # pragma: no cover
logSys.error('json dumps failed: %s', e)
x = '{}'
return x
def _json_loads_safe(x):
try:
x = json.loads(x.decode(
locale.getpreferredencoding(), 'replace'))
except Exception, e: # pragma: no cover
logSys.error('json loads failed: %s', e)
x = {}
return x
sqlite3.register_adapter(dict, _json_dumps_safe)
sqlite3.register_converter("JSON", _json_loads_safe)
def commitandrollback(f): def commitandrollback(f):
@wraps(f) @wraps(f)

View File

@ -802,8 +802,8 @@ class FileContainer:
" encoding) for this jail. Continuing" " encoding) for this jail. Continuing"
" to process line ignoring invalid characters: %r" % " to process line ignoring invalid characters: %r" %
(self.getFileName(), self.getEncoding(), line)) (self.getFileName(), self.getEncoding(), line))
if sys.version_info >= (3,): # In python3, must be decoded # decode with replacing error chars:
line = line.decode(self.getEncoding(), 'ignore') line = line.decode(self.getEncoding(), 'replace')
return line return line
def close(self): def close(self):

View File

@ -177,6 +177,17 @@ class DatabaseTest(LogCaptureTestCase):
self.assertTrue( self.assertTrue(
isinstance(self.db.getBans(jail=self.jail)[0], FailTicket)) isinstance(self.db.getBans(jail=self.jail)[0], FailTicket))
def testAddBanInvalidEncoded(self):
if Fail2BanDb is None: # pragma: no cover
return
self.testAddJail()
ticket = FailTicket("127.0.0.1", 0, {'m': ['... user "\xd1\xe2\xe5\xf2\xe0" ...'], 'a': 1})
self.db.addBan(self.jail, ticket)
self.assertEqual(len(self.db.getBans(jail=self.jail)), 1)
self.assertTrue(
isinstance(self.db.getBans(jail=self.jail)[0], FailTicket))
def testDelBan(self): def testDelBan(self):
self.testAddBan() self.testAddBan()
ticket = self.db.getBans(jail=self.jail)[0] ticket = self.db.getBans(jail=self.jail)[0]