From 10dc47b6840997253e0a86a1d8ba0b3c0a217b96 Mon Sep 17 00:00:00 2001 From: Lemniscate Date: Mon, 27 Jan 2025 11:39:20 +0000 Subject: [PATCH] 27 01 05 - Add Quicksort Specific Checks - Pivot Selection Patterns - Element Swapping Patterns (Done) - Complexity analysis add for quicksort detector (Done) - Implementation of Confidence Calculation for robust detection (Done) -Add Test Cases for Quicksort (Done) --- GOALS.md | 15 ++++++++ RESUME.md | 3 +- dissect/detectors/quicksort.py | 68 ++++++++++++++++++++++++++++++++++ tests/test_quicksort.py | 44 +++++++++++++--------- 4 files changed, 111 insertions(+), 19 deletions(-) diff --git a/GOALS.md b/GOALS.md index ea935cd..92e8f06 100644 --- a/GOALS.md +++ b/GOALS.md @@ -80,7 +80,22 @@ Confidence Aggregation - Function embedding in divide-and-conquer detection (Done) +27 01 05 +- Add Quicksort Specific Checks + - Pivot Selection Patterns + - Element Swapping Patterns +(Done) + - Complexity analysis add for quicksort detector +(Done) + +- Implementation of Confidence Calculation for robust detection +(Done) + +-Add Test Cases for Quicksort +(Done) + +- Test Quicksort - CI/CD Pipeline integration - Automatic algorithm complexity checks diff --git a/RESUME.md b/RESUME.md index 77b0647..adb5f06 100644 --- a/RESUME.md +++ b/RESUME.md @@ -1 +1,2 @@ -25 01 25 \ No newline at end of file +27 01 25 +- Complexity Analysis Mindmap \ No newline at end of file diff --git a/dissect/detectors/quicksort.py b/dissect/detectors/quicksort.py index 93de28d..d8e0a59 100644 --- a/dissect/detectors/quicksort.py +++ b/dissect/detectors/quicksort.py @@ -19,6 +19,30 @@ def detect_quicksort(node, code_bytes): divide_and_conquer = 0 list_operations = 0 complexity = 0 + + # Quicksort-specific checks + def is_partition_loop(node, code_bytes): + loop_code = code_bytes[node['start']:node['end']].decode() + + # Look for pivot selection patterns + pivot_patterns = [ + r'pivot\s*=', # Explicit pivot variable + r'arr\[\s*0\s*\]', # First element selection + r'arr\[\s*-\s*1\s*\]', # Last element selection + r'median_of_three' # Common optimization + ] + + # Look for element swapping + swap_operations = [ + 'arr[i], arr[j] = arr[j], arr[i]', # Python + '[arr[i], arr[j]] = [arr[j], arr[i]]', # JS + 'swap(arr, i, j)' # Common helper + ] + + return ( + any(re.search(p, loop_code) for p in pivot_patterns) and + any(s in loop_code for s in swap_operations) + ) # Analyze function body with context-aware checks for child in normalized_ast['children']: @@ -56,9 +80,53 @@ def detect_quicksort(node, code_bytes): # Complexity analysis + def estimate_complexity(node): + depth = 0 + nested_loops = 0 + + # Traverse AST to find complexity factors + def traverse(n): + nonlocal depth, nested_loops + if n['type'] == 'loop_block': + nested_loops += 1 + depth = max(depth, nested_loops) + for c in n['children']: + traverse(c) + if n['type'] == ['for_statement', 'while_statement']: + nested_loops -= 1 + + traverse(node) + + # Complexity determination + if depth == 1 and 'recursive' in node['operations']: + return 'O(n log n)' # Best Case + elif depth == 2: + return 'O(n^2)' # Worst Case + return 'unknown' + # Confidence Calculation + def calculate_confidence(partition, recursion, complexity): + weights = { + 'partition': 0.5, + 'recursion': 0.3, + 'complexity': 0.2 + } + + score = 0 + if partition: score += weights['partition'] + if recursion: score += weights['recursion'] + + # Complexity bonus + if complexity == 'O(n log n)': + score += 0.2 + elif complexity == 'O(n²)': + score += 0.1 + + return min(score * 1.2, 1.0) # Allow slight overconfidence + + # Final validation check is_quicksort = ( confidence >= 0.65 and # Lowered threshold diff --git a/tests/test_quicksort.py b/tests/test_quicksort.py index e92a16f..679b543 100644 --- a/tests/test_quicksort.py +++ b/tests/test_quicksort.py @@ -1,18 +1,26 @@ - -def partition(arr, low, high): - pivot = arr[high] - i = low - 1 - for j in range(low, high): - if arr[j] <= pivot: - i += 1 - arr[i], arr[j] = arr[j], arr[i] - arr[i+1], arr[high] = arr[high], arr[i+1] - return i+1 - -def quicksort(arr, low=0, high=None): - if high is None: - high = len(arr) - 1 - if low < high: - pi = partition(arr, low, high) - quicksort(arr, low, pi-1) - quicksort(arr, pi+1, high) \ No newline at end of file +# tests/test_quicksort.py +TEST_CASES = [ + { + "code": """ + def quicksort(arr): + if len(arr) <= 1: return arr + pivot = arr[0] + less = [x for x in arr[1:] if x <= pivot] + greater = [x for x in arr[1:] if x > pivot] + return quicksort(less) + [pivot] + quicksort(greater) + """, + "expected": True, + "complexity": "O(n log n)" + }, + { + "code": """ + def fake_sort(arr): # Looks like quicksort but isn't + if len(arr) < 2: return arr + mid = arr[len(arr)//2] + left = [x for x in arr if x < mid] + right = [x for x in arr if x > mid] + return fake_sort(left) + [mid] + fake_sort(right) + """, + "expected": False + } +] \ No newline at end of file