From 71391874eb2696a31fdaa7cb43fee4eb5c4ab51f Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Sun, 16 Jan 2011 10:52:42 +0000 Subject: [PATCH] slightly faster and thread safer inference --- lib/controller/checks.py | 10 ++++++---- lib/core/common.py | 7 ++++--- lib/core/option.py | 3 --- lib/core/threads.py | 14 ++++++++------ lib/request/comparison.py | 21 +++++++++------------ lib/techniques/blind/inference.py | 3 --- lib/techniques/brute/use.py | 4 ---- 7 files changed, 27 insertions(+), 35 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 76d0bafc2..535b9fda6 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -51,6 +51,7 @@ from lib.core.exception import sqlmapUserQuitException from lib.core.session import setDynamicMarkings from lib.core.settings import CONSTANT_RATIO from lib.core.settings import UPPER_RATIO_BOUND +from lib.core.threads import getCurrentThreadData from lib.core.unescaper import unescaper from lib.request.connect import Connect as Request from lib.request.templates import getPageTemplate @@ -594,12 +595,13 @@ def checkDynamicContent(firstPage, secondPage): debugMsg += "because NULL connection used" logger.debug(debugMsg) return - - conf.seqMatcher.set_seq1(firstPage) - conf.seqMatcher.set_seq2(secondPage) + + seqMatcher = getCurrentThreadData().seqMatcher + seqMatcher.set_seq1(firstPage) + seqMatcher.set_seq2(secondPage) # In case of an intolerable difference turn on dynamicity removal engine - if conf.seqMatcher.quick_ratio() <= UPPER_RATIO_BOUND: + if seqMatcher.quick_ratio() <= UPPER_RATIO_BOUND: findDynamicContent(firstPage, secondPage) count = 0 diff --git a/lib/core/common.py b/lib/core/common.py index d29714d51..fb065b42c 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -2080,10 +2080,11 @@ def getComparePageRatio(firstPage, secondPage, filtered=False): if filtered: (firstPage, secondPage) = map(getFilteredPageContent, (firstPage, secondPage)) - conf.seqMatcher.set_seq1(firstPage) - conf.seqMatcher.set_seq2(secondPage) + seqMatcher = getCurrentThreadData().seqMatcher + seqMatcher.set_seq1(firstPage) + seqMatcher.set_seq2(secondPage) - return conf.seqMatcher.quick_ratio() + return seqMatcher.quick_ratio() def openFile(filename, mode='r'): """ diff --git a/lib/core/option.py b/lib/core/option.py index 6e0f00f01..19d4e9bc6 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1077,8 +1077,6 @@ def __setConfAttributes(): conf.port = None conf.redirectHandled = False conf.scheme = None - #conf.seqMatcher = difflib.SequenceMatcher(lambda x: x in " \t") - conf.seqMatcher = difflib.SequenceMatcher(None) conf.sessionFP = None conf.start = True conf.tests = [] @@ -1135,7 +1133,6 @@ def __setKnowledgeBaseAttributes(flushAll=True): kb.locks = advancedDict() kb.locks.cacheLock = threading.Lock() kb.locks.logLock = threading.Lock() - kb.locks.seqLock = None kb.matchRatio = None kb.nullConnection = None diff --git a/lib/core/threads.py b/lib/core/threads.py index 9dec6557b..159dcd4fa 100644 --- a/lib/core/threads.py +++ b/lib/core/threads.py @@ -7,6 +7,7 @@ Copyright (c) 2006-2010 sqlmap developers (http://sqlmap.sourceforge.net/) See the file 'doc/COPYING' for copying permission """ +import difflib import threading from lib.core.data import kb @@ -17,12 +18,13 @@ class ThreadData(): """ def __init__(self): - self.disableStdOut = False - self.lastErrorPage = None - self.lastHTTPError = None - self.lastQueryDuration = 0 - self.lastRequestUID = 0 - self.valueStack = [] + self.disableStdOut = False + self.lastErrorPage = None + self.lastHTTPError = None + self.lastQueryDuration = 0 + self.lastRequestUID = 0 + self.seqMatcher = difflib.SequenceMatcher(None) + self.valueStack = [] def getCurrentThreadUID(): return hash(threading.currentThread()) diff --git a/lib/request/comparison.py b/lib/request/comparison.py index 81cffa954..328aaa22f 100644 --- a/lib/request/comparison.py +++ b/lib/request/comparison.py @@ -22,13 +22,16 @@ from lib.core.settings import CONSTANT_RATIO from lib.core.settings import DIFF_TOLERANCE from lib.core.settings import LOWER_RATIO_BOUND from lib.core.settings import UPPER_RATIO_BOUND +from lib.core.threads import getCurrentThreadData def comparison(page, getSeqMatcher=False, pageLength=None): if page is None and pageLength is None: return None regExpResults = None - conf.seqMatcher.set_seq1(kb.pageTemplate) + + seqMatcher = getCurrentThreadData().seqMatcher + seqMatcher.set_seq1(kb.pageTemplate) if page: # String to be excluded before calculating page hash @@ -66,28 +69,22 @@ def comparison(page, getSeqMatcher=False, pageLength=None): # Dynamic content lines to be excluded before comparison if not kb.nullConnection: page = removeDynamicContent(page) - conf.seqMatcher.set_seq1(removeDynamicContent(kb.pageTemplate)) + seqMatcher.set_seq1(removeDynamicContent(kb.pageTemplate)) if not pageLength: pageLength = len(page) - if kb.locks.seqLock: - kb.locks.seqLock.acquire() - if conf.textOnly: - (conf.seqMatcher.a, page) = map(getFilteredPageContent, (conf.seqMatcher.a, page)) + (seqMatcher.a, page) = map(getFilteredPageContent, (seqMatcher.a, page)) if not conf.eRegexp and not conf.eString and kb.nullConnection and pageLength: - ratio = 1. * pageLength / len(conf.seqMatcher.a) + ratio = 1. * pageLength / len(seqMatcher.a) if ratio > 1.: ratio = 1. / ratio else: - conf.seqMatcher.set_seq2(page) - ratio = round(conf.seqMatcher.quick_ratio(), 3) - - if kb.locks.seqLock: - kb.locks.seqLock.release() + seqMatcher.set_seq2(page) + ratio = round(seqMatcher.quick_ratio(), 3) # If the url is stable and we did not set yet the match ratio and the # current injected value changes the url page content diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py index b6e951b52..3615989e2 100644 --- a/lib/techniques/blind/inference.py +++ b/lib/techniques/blind/inference.py @@ -257,7 +257,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None idxlock = threading.Lock() iolock = threading.Lock() valuelock = threading.Lock() - kb.locks.seqLock = threading.Lock() kb.threadContinue = True def downloadThread(): @@ -404,8 +403,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None if conf.verbose in (1, 2) and not showEta and infoMsg: dataToStdout(infoMsg) - kb.locks.seqLock = None - # No multi-threading (--threads = 1) else: index = firstChar diff --git a/lib/techniques/brute/use.py b/lib/techniques/brute/use.py index 746b30309..6a9ee6d1f 100644 --- a/lib/techniques/brute/use.py +++ b/lib/techniques/brute/use.py @@ -54,7 +54,6 @@ def tableExists(tableFile, regex=None): threads = [] tbllock = threading.Lock() iolock = threading.Lock() - kb.locks.seqLock = threading.Lock() kb.threadContinue = True kb.suppressSession = True @@ -130,7 +129,6 @@ def tableExists(tableFile, regex=None): except KeyboardInterrupt: raise sqlmapThreadException, "user aborted" finally: - kb.locks.seqLock = None kb.threadContinue = True kb.threadException = False kb.suppressSession = False @@ -172,7 +170,6 @@ def columnExists(columnFile, regex=None): threads = [] collock = threading.Lock() iolock = threading.Lock() - kb.locks.seqLock = threading.Lock() kb.threadContinue = True kb.suppressSession = True @@ -239,7 +236,6 @@ def columnExists(columnFile, regex=None): except KeyboardInterrupt: raise sqlmapThreadException, "user aborted" finally: - kb.locks.seqLock = None kb.threadContinue = True kb.threadException = False kb.suppressSession = False