├── requirements.txt ├── config.ini ├── Evaluation ├── model_output.txt ├── ground_truth.txt ├── Evaluation.py └── README.md ├── embedding_retriever.py ├── document_processor.py ├── Correction.py ├── README.md ├── fidelity_ghidra.c ├── variabledependency.py ├── pattern_matcher.py ├── testdata └── test.txt ├── FidelityGPT.py ├── fidelity_new.c ├── prompt_templates.py └── Dataset ├── curl.txt └── SQLite.txt /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZhouZhiping045/FidelityGPT/HEAD/requirements.txt -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | [LLM] 2 | model = gpt-4o 3 | temperature = 0 4 | api_key =sk-XXXXXX 5 | api_base =XXXXX 6 | 7 | 8 | 9 | [PATHS] 10 | ; Input path 11 | input_dir = test_input 12 | 13 | ; Output path 14 | output_dir = test_output 15 | 16 | ; Decompilation distortion database path 17 | knowledge_base = fidelity_new.c 18 | 19 | ; Decompilation distortion database: IDA Pro uses fidelity_new.c, Ghidra uses fidelity_ghidra.c -------------------------------------------------------------------------------- /Evaluation/model_output.txt: -------------------------------------------------------------------------------- 1 | undefined4 isAlterableTable(undefined4 *param_1,undefined4 *param_2) 2 | { 3 | { 4 | int iVar1; 5 | undefined4 uVar2; 6 | iVar1 = sqlite3_strnicmp(*param_2,&UNK_000cd86c,7); // I2 7 | if (iVar1 == 0) { 8 | LAB_00071604: 9 | sqlite3ErrorMsg(param_1,&UNK_000cd874,*param_2); // I2 10 | uVar2 = 1; 11 | } 12 | else { 13 | if ((param_2[9] & 0x1000) != 0) { 14 | iVar1 = sqlite3ReadOnlyShadowTables(*param_1); 15 | if (iVar1 != 0) goto LAB_00071604; 16 | } 17 | uVar2 = 0; 18 | } 19 | return uVar2; 20 | } 21 | ///// 22 | void renameReloadSchema(int param_1,int param_2) 23 | { 24 | { 25 | undefined4 uVar1; // I4 26 | uVar1 = 0x7168f; 27 | if (*(int *)(param_1 + 8) != 0) { // I1 28 | sqlite3ChangeCookie(param_1,param_2); 29 | sqlite3VdbeAddParseSchemaOp(*(undefined4 *)(param_1 + 8),param_2,0,uVar1); // I1 30 | if (param_2 != 1) { 31 | sqlite3VdbeAddParseSchemaOp(*(undefined4 *)(param_1 + 8),1,0,uVar1); // I1 32 | } 33 | } 34 | return; // I5 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Evaluation/ground_truth.txt: -------------------------------------------------------------------------------- 1 | undefined4 isAlterableTable(undefined4 *param_1,undefined4 *param_2) 2 | { 3 | { 4 | int iVar1; // I4 5 | undefined4 uVar2; // I4 6 | iVar1 = sqlite3_strnicmp(*param_2,&UNK_000cd86c,7); // I1 7 | if (iVar1 == 0) { 8 | LAB_00071604: 9 | sqlite3ErrorMsg(param_1,&UNK_000cd874,*param_2); // I2 10 | uVar2 = 1; 11 | } 12 | else { 13 | if ((param_2[9] & 0x1000) != 0) { // I1 14 | iVar1 = sqlite3ReadOnlyShadowTables(*param_1); // I1 15 | if (iVar1 != 0) goto LAB_00071604; 16 | } 17 | uVar2 = 0; 18 | } 19 | return uVar2; 20 | } 21 | ///// 22 | void renameReloadSchema(int param_1,int param_2) 23 | { 24 | { 25 | undefined4 uVar1; // I4 26 | uVar1 = 0x7168f; // I2 27 | if (*(int *)(param_1 + 8) != 0) { // I1 28 | sqlite3ChangeCookie(param_1,param_2); 29 | sqlite3VdbeAddParseSchemaOp(*(undefined4 *)(param_1 + 8),param_2,0,uVar1); // I1 30 | if (param_2 != 1) { 31 | sqlite3VdbeAddParseSchemaOp(*(undefined4 *)(param_1 + 8),1,0,uVar1); // I1 32 | } 33 | } 34 | return; // I5 35 | } 36 | } -------------------------------------------------------------------------------- /embedding_retriever.py: -------------------------------------------------------------------------------- 1 | from langchain_openai import OpenAIEmbeddings 2 | from langchain_community.vectorstores import Chroma 3 | 4 | import os 5 | from langchain.embeddings import OpenAIEmbeddings 6 | from langchain.vectorstores import Chroma 7 | 8 | def create_embedding(texts): 9 | embeddings = OpenAIEmbeddings(model='text-embedding-ada-002') 10 | return embeddings 11 | 12 | def create_vectorstore(texts, embeddings): 13 | db = Chroma.from_texts(texts, embeddings) 14 | return db 15 | 16 | def create_retriever(db): 17 | retriever = db.as_retriever(search_type="similarity", search_kwargs={"k": 1}) 18 | return retriever 19 | 20 | def retrieve_documents(retriever, sub_queries): 21 | retrieved_docs = [] 22 | for sub_query in sub_queries: 23 | sub_query = sub_query.strip() 24 | if sub_query: 25 | # print(f"Retrieving for sub-query: '{sub_query}'") 26 | results = retriever.get_relevant_documents(sub_query) 27 | for result in results: 28 | if isinstance(result.page_content, str): 29 | retrieved_docs.append(result.page_content) 30 | else: 31 | print(f"Non-string result found: {result.page_content}") 32 | return retrieved_docs 33 | -------------------------------------------------------------------------------- /document_processor.py: -------------------------------------------------------------------------------- 1 | class Document: 2 | def __init__(self, page_content, metadata=None): 3 | self.page_content = page_content 4 | self.metadata = metadata if metadata is not None else {} 5 | 6 | 7 | def load_document(file_path): 8 | try: 9 | with open(file_path, "r", encoding="utf-8") as f: 10 | content = f.read() 11 | print(f"File content length: {len(content)}") 12 | return content 13 | except FileNotFoundError: 14 | print(f"Error: The file '{file_path}' was not found.") 15 | exit() 16 | except Exception as e: 17 | print(f"Error: {e}") 18 | exit() 19 | 20 | 21 | def split_document(content): 22 | lines = content.splitlines() 23 | documents = [Document(line) for line in lines if line.strip()] 24 | return documents 25 | 26 | 27 | def read_queries(file_path): 28 | try: 29 | with open(file_path, "r", encoding="utf-8") as f: 30 | content = f.read() 31 | 32 | queries = [query.strip() for query in content.split("/////") if query.strip()] 33 | split_queries = [] 34 | 35 | for query in queries: 36 | lines = query.splitlines() 37 | while len(lines) > 500: 38 | split_queries.append("\n".join(lines[:500])) 39 | lines = lines[500:] 40 | split_queries.append("\n".join(lines)) 41 | 42 | return split_queries 43 | except FileNotFoundError: 44 | print(f"Error: The file '{file_path}' was not found.") 45 | exit() 46 | except Exception as e: 47 | print(f"Error: {e}") 48 | exit() 49 | 50 | 51 | def write_output(file_path, results): 52 | try: 53 | with open(file_path, "w", encoding="utf-8") as f: 54 | f.write(results) 55 | except Exception as e: 56 | print(f"Error: {e}") 57 | exit() 58 | -------------------------------------------------------------------------------- /Correction.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from document_processor import read_queries, write_output 3 | from prompt_templates import create_RAG_correction_template 4 | from langchain_openai import ChatOpenAI 5 | from langchain.schema import HumanMessage 6 | import configparser 7 | import os 8 | 9 | CUR_DIR = os.path.dirname(os.path.abspath(__file__)) 10 | CONFIG = os.path.join(CUR_DIR, 'config.ini') 11 | 12 | def load_config(field: str, value: str) -> str: 13 | config = configparser.ConfigParser() 14 | config.read(CONFIG) 15 | return config[field][value] 16 | 17 | 18 | os.environ["OPENAI_API_BASE"] = load_config('LLM', 'api_base') 19 | os.environ["OPENAI_API_KEY"] = load_config('LLM', 'api_key') 20 | 21 | def read_and_split_queries(file_path): 22 | print(f"Reading and splitting queries from {file_path}") 23 | with open(file_path, 'r', encoding='utf-8') as f: 24 | content = f.read() 25 | queries = content.split('/////') 26 | print(f"Total {len(queries)} queries found.") 27 | return queries 28 | 29 | def process_file(file_path, output_dir, llm, rag_correction_template): 30 | queries = read_and_split_queries(file_path) 31 | results = [] 32 | 33 | for query_index, query in enumerate(queries): 34 | query = query.strip() 35 | if not query: 36 | continue 37 | 38 | print(f"Processing query {query_index + 1}: {query}") 39 | 40 | 41 | prompt_text = rag_correction_template.format(context="", question=query) 42 | print(f"RAG correction prompt: {prompt_text}") 43 | 44 | result = llm.invoke([HumanMessage(content=prompt_text)]).content.strip() 45 | results.append(f"Query {query_index + 1}:\n{result}\n") 46 | 47 | print(f"Results for query {query_index + 1} have been processed.") 48 | 49 | 50 | base_filename = os.path.basename(file_path).split('.')[0] 51 | output_path = os.path.join(output_dir, f"{base_filename}_RAG_Correct.txt") 52 | print(f"Writing results to {output_path}") 53 | write_output(output_path, "\n/////\n".join(results)) 54 | 55 | def main(): 56 | parser = argparse.ArgumentParser(description="Process text queries with RAG correction.") 57 | parser.add_argument('--input_dir', type=str, default='correction_input', help="Input directory containing query files.") 58 | parser.add_argument('--output_dir', type=str, default='correction_output', help="Output directory for results.") 59 | args = parser.parse_args() 60 | 61 | current_dir = os.getcwd() 62 | testdata_dir = os.path.join(current_dir, args.input_dir) 63 | output_dir = os.path.join(current_dir, args.output_dir) 64 | 65 | if not os.path.exists(output_dir): 66 | os.makedirs(output_dir) 67 | 68 | 69 | model_name = load_config("LLM", "model") 70 | temperature = float(load_config("LLM", "temperature")) 71 | llm = ChatOpenAI(model=model_name, temperature=temperature) 72 | rag_correction_template = create_RAG_correction_template() 73 | 74 | for root, dirs, files in os.walk(testdata_dir): 75 | for file in files: 76 | file_path = os.path.join(root, file) 77 | print(f"Processing file: {file_path}") 78 | process_file(file_path, output_dir, llm, rag_correction_template) 79 | 80 | print("All files have been processed and results have been written to the output directory.") 81 | 82 | if __name__ == "__main__": 83 | main() 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 |
4 | FidelityGPT Logo 5 | 7 |

FidelityGPT: Correcting Decompilation Distortions with Retrieval Augmented Generation

8 |
11 | 12 | 13 | 14 | ## 📁 Artifact Structure 15 | 16 | ``` 17 | ├── Dataset/ # Decompiled functions (///// separated) 18 | ├── Ground truth/ # Ground truth functions (///// separated) 19 | ├── Evaluation/ # Evaluation script 20 | ├── testdata/ # Raw test data (txt) 21 | ├── config.ini # System configuration 22 | ├── FidelityGPT.py # Distortion detection 23 | ├── Correction.py # Distortion correction 24 | ├── prompt_templates.py # Prompt templates for all LLM tasks 25 | ├── pattern_matcher.py # Dynamic Semantic Intensity Retrieval Algorithm 26 | ├── variabledependency.py # Variable Dependency Algorithm 27 | ├── document_processor.py # Utility for document formatting 28 | ├── embedding_retriever.py # RAG embedding retrieval logic 29 | ├── fidelity_new.c # Distortion DB (for IDA Pro) 30 | ├── fidelity_ghidra.c # Distortion DB (for Ghidra) 31 | ├── requirements.txt # Python dependencies 32 | ├── README.md # This file 33 | ``` 34 | 35 | ## ⚙️ Configuration 36 | 37 | Before running the system, update `config.ini`: 38 | 39 | ```ini 40 | [LLM] 41 | model = gpt-4o 42 | temperature = 0 43 | api_key = sk-XXXX 44 | api_base = XXXX 45 | 46 | [PATHS] 47 | input_dir = Dataset_4_AE ; Folder for input decompiled functions 48 | output_dir = Dataset_4_AE_output ; Folder for storing detection/correction results 49 | knowledge_base = fidelity_new.c ; Use `fidelity_ghidra.c` if using Ghidra 50 | ``` 51 | 52 | - Input functions: `.txt` files, each with functions separated by `/////` 53 | - Distortion DB: `fidelity_new.c` (IDA Pro) or `fidelity_ghidra.c` (Ghidra) 54 | 55 | ## 🧪 Step-by-Step Execution 56 | 57 | ### 1. Prepare Input Files 58 | 59 | Move test functions into the input folder: 60 | 61 | ```bash 62 | mkdir Dataset_4_AE 63 | cp testdata/*.txt Dataset_4_AE/ 64 | ``` 65 | 66 | > You may also copy `Dataset/*.txt` into `Dataset_4_AE/` if needed: 67 | ```bash 68 | cp Dataset/*.txt Dataset_4_AE/ 69 | ``` 70 | 71 | ### 2. Run Distortion Detection 72 | 73 | ```bash 74 | python FidelityGPT.py 75 | ``` 76 | 77 | - Input: Files from `Dataset_4_AE/` 78 | - Output: Stored in `Dataset_4_AE_output/` 79 | - Each line is labeled with distortion type `I1`–`I6` 80 | - Functions are separated using `/////` 81 | 82 | > ℹ️ For functions longer than 50 lines, the system uses **chunk-based detection** with a 5-line overlap. 83 | After detection (before running Correction or Evaluation): 84 | 85 | After detection: 86 | - Manually merge chunked functions 87 | - Remove overlapping duplicate lines 88 | - Preserve the ///// separator 89 | 90 | ⚠️ Ensure line alignment: each line in model_output.txt should correspond exactly to the same function segment in ground_truth.txt. Since functions longer than 50 lines were split into chunks during preprocessing, manual alignment may be required. 91 | 92 | 👉 In our practice, we place ground_truth.txt and model_output.txt in two columns of an Excel sheet to ensure proper alignment before running Correction or Evaluation. 93 | 94 | ### 3. Run Correction (Optional) 95 | 96 | ```bash 97 | python Correction.py 98 | ``` 99 | 100 | ### 4. Run Evaluation 101 | 102 | Ensure the following: 103 | - `Ground truth/ground_truth.txt`: aligned reference results 104 | - `model_output.txt`: post-processed output from detection (line-aligned) 105 | 106 | Then run: 107 | 108 | ```bash 109 | python Evaluation/Evaluation.py 110 | ``` 111 | 112 | For the correction phase, manual evaluation is required. Please refer to Table I in the paper as the guideline for manual assessment. 113 | 114 | ## 🧠 Key Components 115 | 116 | | Script | Description | 117 | |--------|-------------| 118 | | `FidelityGPT.py` | Main detection pipeline | 119 | | `Correction.py` | Fixes distorted code lines | 120 | | `prompt_templates.py` | LLM prompt templates | 121 | | `pattern_matcher.py` | Semantic intensity retrieval | 122 | | `variabledependency.py` | Variable dependency analysis | 123 | | `Evaluation/Evaluation.py` | Compares against ground truth | 124 | | `fidelity_new.c` / `fidelity_ghidra.c` | RAG knowledge base | 125 | 126 | ## ✅ Requirements 127 | 128 | ```bash 129 | pip install -r requirements.txt 130 | ``` 131 | -------------------------------------------------------------------------------- /Evaluation/Evaluation.py: -------------------------------------------------------------------------------- 1 | import re 2 | from collections import defaultdict 3 | 4 | def read_file(file_path): 5 | with open(file_path, 'r', encoding='utf-8') as file: 6 | return file.read() 7 | 8 | def extract_lines_with_annotations(file_content): 9 | pattern = re.compile(r'(.*?)(//\s*I\d)') 10 | lines_with_annotations = [] 11 | for line_number, line in enumerate(file_content.split('\n'), start=1): 12 | match = pattern.search(line) 13 | if match: 14 | code_line = match.group(1).strip() 15 | annotation = match.group(2).replace(" ", "") 16 | lines_with_annotations.append((line_number, code_line, annotation)) 17 | else: 18 | lines_with_annotations.append((line_number, line.strip(), None)) 19 | return lines_with_annotations 20 | 21 | def normalize_code_line(line): 22 | line = line.replace("\\\\", "\\").replace("\\t", "\t").replace("\\n", "\n") 23 | return line 24 | 25 | def compare_annotations(gt_lines, model_lines): 26 | tp = 0 27 | tn = 0 28 | fp = 0 29 | fn = 0 30 | 31 | gt_dict = {normalize_code_line(code): (line_number, annotation) for line_number, code, annotation in gt_lines if annotation} 32 | model_dict = {normalize_code_line(code): (line_number, annotation) for line_number, code, annotation in model_lines if annotation} 33 | 34 | fp_lines = [] 35 | fn_lines = [] 36 | 37 | for code in gt_dict: 38 | if code in model_dict: 39 | if gt_dict[code][1] == model_dict[code][1]: 40 | tp += 1 41 | else: 42 | 43 | continue 44 | else: 45 | fn += 1 46 | fn_lines.append((gt_dict[code][0], code, gt_dict[code][1])) 47 | 48 | for code in model_dict: 49 | if code not in gt_dict: 50 | fp += 1 51 | fp_lines.append((model_dict[code][0], code, model_dict[code][1])) 52 | 53 | tn = len(gt_lines) - tp - fn 54 | 55 | return tp, tn, fp, fn, sorted(fp_lines), sorted(fn_lines) 56 | 57 | def compare_annotations_by_label(gt_lines, model_lines): 58 | results = defaultdict(lambda: {'tp': 0, 'tn': 0, 'fp': 0, 'fn': 0}) 59 | 60 | gt_dict = {normalize_code_line(code): annotation for line_number, code, annotation in gt_lines if annotation} 61 | model_dict = {normalize_code_line(code): annotation for line_number, code, annotation in model_lines if annotation} 62 | 63 | all_labels = ['//I1', '//I2', '//I3', '//I4', '//I5', '//I6'] 64 | 65 | for code in gt_dict: 66 | gt_annotation = gt_dict[code] 67 | if code in model_dict: 68 | model_annotation = model_dict[code] 69 | if gt_annotation == model_annotation: 70 | results[gt_annotation]['tp'] += 1 71 | else: 72 | continue 73 | else: 74 | results[gt_annotation]['fn'] += 1 75 | 76 | for code in model_dict: 77 | if code not in gt_dict: 78 | model_annotation = model_dict[code] 79 | results[model_annotation]['fp'] += 1 80 | 81 | for label in all_labels: 82 | total_lines = len(gt_lines) 83 | results[label]['tn'] = total_lines - results[label]['tp'] - results[label]['fn'] 84 | 85 | return results, all_labels 86 | 87 | def calculate_metrics(tp, tn, fp, fn): 88 | accuracy = (tp + tn) / (tp + tn + fp + fn) if (tp + tn + fp + fn) > 0 else 0 89 | precision = tp / (tp + fp) if (tp + fp) > 0 else 0 90 | recall = tp / (tp + fn) if (tp + fn) > 0 else 0 91 | f1_score = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0 92 | specificity = tn / (tn + fp) if (tn + fp) > 0 else 0 93 | 94 | return accuracy, precision, recall, f1_score, specificity 95 | 96 | def main(): 97 | ground_truth_file = 'ground_truth.txt' 98 | model_output_file = 'model_output.txt' 99 | 100 | ground_truth_content = read_file(ground_truth_file) 101 | model_output_content = read_file(model_output_file) 102 | 103 | ground_truth_annotations = extract_lines_with_annotations(ground_truth_content) 104 | model_output_annotations = extract_lines_with_annotations(model_output_content) 105 | 106 | tp, tn, fp, fn, fp_lines, fn_lines = compare_annotations(ground_truth_annotations, model_output_annotations) 107 | 108 | overall_accuracy, overall_precision, overall_recall, overall_f1_score, overall_specificity = calculate_metrics(tp, tn, fp, fn) 109 | 110 | print("Overall Metrics:") 111 | print(f" Accuracy: {overall_accuracy:.2f}") 112 | print(f" Precision: {overall_precision:.2f}") 113 | 114 | 115 | 116 | if __name__ == "__main__": 117 | main() -------------------------------------------------------------------------------- /Evaluation/README.md: -------------------------------------------------------------------------------- 1 | # Manual Alignment Guide for Evaluation 2 | 3 | During **distortion detection**, functions longer than 50 lines are automatically split into **chunks** with a 5-line overlap. 4 | Before running **Correction** or **Evaluation**, these chunked functions must be **manually merged** back into a single function. 5 | This ensures line-alignment with the ground truth. 6 | 7 | --- 8 | 9 | ## Steps for Manual Alignment 10 | 11 | 1. **Identify Split Blocks** 12 | - Functions are split into multiple blocks (e.g., *Query 1, Block 1* and *Query 1, Block 2*). 13 | - Each block may share overlapping lines due to the 5-line sliding window. 14 | 15 | 2. **Merge Blocks** 16 | - Concatenate the split blocks in order. 17 | - **Remove overlapping duplicate lines** caused by the chunking. 18 | 19 | 3. **Preserve Function Separator** 20 | - After merging, ensure that functions are still separated by `/////` 21 | 22 | 4. **Check Alignment with Ground Truth** 23 | - The merged function should correspond line-by-line with the ground truth. 24 | - Verify alignment using an Excel sheet or side-by-side comparison if needed. 25 | 26 | --- 27 | 28 | ## Example 29 | 30 | ### Query 1, Block 1: 31 | ```c 32 | __cdecl main(int argc, const char **argv, const char **envp) 33 | { 34 | char *v3; //I4 35 | char *v4; //I4 36 | void *v5; //I4 37 | const char *v6; //I4 38 | char v10; 39 | char v11; 40 | const char *v12; 41 | int v13; //I4 42 | v10 = 0; 43 | v11 = 0; 44 | v12 = 0; 45 | set_program_name(*argv); 46 | setlocale(6, byte_177CC); //I2 47 | bindtextdomain("coreutils", "/usr/local/share/locale"); 48 | textdomain("coreutils"); 49 | atexit((void (__fastcall *)(void *))close_stdout); //I6 50 | while ( 1 ) 51 | { 52 | v13 = rpl_getopt_long(argc, argv, "+as:z", (const char **)&longopts, 0); //I6 53 | if ( v13 == -1 ) 54 | break; 55 | if ( v13 == 97 ) //I2 56 | goto LABEL_12; 57 | if ( v13 <= 97 ) 58 | { 59 | if ( v13 == -3 ) 60 | { 61 | version_etc((FILE *)stdout, "basename", "GNU coreutils", Version, "David MacKenzie", 0); //I6 62 | exit(0); 63 | } 64 | if ( v13 == -2 ) 65 | usage(0); 66 | LABEL_16: 67 | usage(1); 68 | } 69 | if ( v13 == 115 ) //I2 70 | { 71 | v12 = (const char *)rpl_optarg; //I6 72 | LABEL_12: 73 | v10 = 1; 74 | } 75 | else 76 | { 77 | if ( v13 != 122 ) //I2 78 | goto LABEL_16; 79 | v11 = 1; 80 | } 81 | } 82 | } 83 | ``` 84 | ### Query 1, Block 2: 85 | ```c 86 | if ( v13 != 122 ) //I2 87 | goto LABEL_16; 88 | v11 = 1; 89 | } 90 | } 91 | if ( argc < rpl_optind + 1 ) 92 | { 93 | v3 = gettext("missing operand"); 94 | error(0, 0, v3); 95 | usage(1); 96 | } 97 | if ( v10 != 1 && argc > rpl_optind + 2 ) 98 | { 99 | v4 = gettext("extra operand %s"); 100 | v5 = quote((int)argv[rpl_optind + 2]); //I1 101 | error(0, 0, v4, v5); 102 | usage(1); 103 | } 104 | if ( v10 ) 105 | { 106 | while ( argc > rpl_optind ) 107 | { 108 | perform_basename((char *)argv[rpl_optind], v12, v11); //I1 109 | ++rpl_optind; 110 | } 111 | } 112 | else 113 | { 114 | if ( argc == rpl_optind + 2 ) 115 | v6 = argv[rpl_optind + 1]; 116 | else 117 | v6 = 0; 118 | perform_basename((char *)argv[rpl_optind], v6, v11); //I1 119 | } 120 | return 0; 121 | ``` 122 | ✅ Merged Function 123 | ```c 124 | __cdecl main(int argc, const char **argv, const char **envp) 125 | { 126 | char *v3; //I4 127 | char *v4; //I4 128 | void *v5; //I4 129 | const char *v6; //I4 130 | char v10; 131 | char v11; 132 | const char *v12; 133 | int v13; //I4 134 | v10 = 0; 135 | v11 = 0; 136 | v12 = 0; 137 | set_program_name(*argv); 138 | setlocale(6, byte_177CC); //I2 139 | bindtextdomain("coreutils", "/usr/local/share/locale"); 140 | textdomain("coreutils"); 141 | atexit((void (__fastcall *)(void *))close_stdout); //I6 142 | while ( 1 ) 143 | { 144 | v13 = rpl_getopt_long(argc, argv, "+as:z", (const char **)&longopts, 0); //I6 145 | if ( v13 == -1 ) 146 | break; 147 | if ( v13 == 97 ) //I2 148 | goto LABEL_12; 149 | if ( v13 <= 97 ) 150 | { 151 | if ( v13 == -3 ) 152 | { 153 | version_etc((FILE *)stdout, "basename", "GNU coreutils", Version, "David MacKenzie", 0); //I6 154 | exit(0); 155 | } 156 | if ( v13 == -2 ) 157 | usage(0); 158 | LABEL_16: 159 | usage(1); 160 | } 161 | if ( v13 == 115 ) //I2 162 | { 163 | v12 = (const char *)rpl_optarg; //I6 164 | LABEL_12: 165 | v10 = 1; 166 | } 167 | else 168 | { 169 | if ( v13 != 122 ) //I2 170 | goto LABEL_16; 171 | v11 = 1; 172 | } 173 | } 174 | if ( argc < rpl_optind + 1 ) 175 | { 176 | v3 = gettext("missing operand"); 177 | error(0, 0, v3); 178 | usage(1); 179 | } 180 | if ( v10 != 1 && argc > rpl_optind + 2 ) 181 | { 182 | v4 = gettext("extra operand %s"); 183 | v5 = quote((int)argv[rpl_optind + 2]); //I1 184 | error(0, 0, v4, v5); 185 | usage(1); 186 | } 187 | if ( v10 ) 188 | { 189 | while ( argc > rpl_optind ) 190 | { 191 | perform_basename((char *)argv[rpl_optind], v12, v11); //I1 192 | ++rpl_optind; 193 | } 194 | } 195 | else 196 | { 197 | if ( argc == rpl_optind + 2 ) 198 | v6 = argv[rpl_optind + 1]; 199 | else 200 | v6 = 0; 201 | perform_basename((char *)argv[rpl_optind], v6, v11); //I1 202 | } 203 | return 0; 204 | } 205 | ``` 206 | Key Notes: 207 | 208 | - Always merge before running Correction and Evaluation. 209 | - Remove only the overlapping lines, not the unique ones. 210 | - Keep the ///// separator intact between functions. 211 | -------------------------------------------------------------------------------- /fidelity_ghidra.c: -------------------------------------------------------------------------------- 1 | fprintf(*(FILE **)(lVar1 + 8),"%.*x",(ulong)param_3,param_2); // I1 Pointer arithmetic to access struct members 2 | (*p_free)(*(undefined8 *)(param_1 + 0x18)); // I1 Pointer arithmetic to access struct members 3 | *(int *)(param_1 + 0x10) = *(int *)(param_1 + 0x10) + 1; // I1 Pointer arithmetic to access struct members 4 | *(long *)(*param_1 + 0x28) = lVar3 + 0x20; // I1 Pointer arithmetic to access struct members 5 | *(long *)(lVar3 + 0x20) = *param_1; // I1 Pointer arithmetic to access struct members 6 | *(long **)(lVar3 + 0x28) = param_1; // I1 Pointer arithmetic to access struct members 7 | *(ulong *)(param_2 + 0x18) = (ulong)param_1; // I1 Pointer arithmetic to access struct members 8 | *(undefined *)(param_1 + 0x85) = 1; // I1 Pointer arithmetic to access struct members 9 | *(undefined *)(param_1 + 0x86) = 0; // I1 Pointer arithmetic to access struct members 10 | *(undefined4 *)((long)pvVar1 + 0x2001c) = param_1; // I1 Pointer arithmetic to access struct members 11 | *(undefined4 *)((long)pvVar1 + 0xc) = 0; // I1 Pointer arithmetic to access struct members 12 | *(undefined4 *)((long)pvVar1 + 8) = 0; // I1 Pointer arithmetic to access struct members 13 | *(undefined8 *)(*(long *)(param_1 + 0x20) + 0x40) = 0; // I1 Pointer arithmetic to access struct members 14 | *(undefined8 *)(*(long *)(param_1 + 0x20) + 0x40) = param_2; // I1 Pointer arithmetic to access struct members 15 | *(undefined8 *)(param_1 + 0x18) = param_2; // I1 Pointer arithmetic to access struct members 16 | *(undefined8 *)(param_1 + 0x20) = param_2; // I1 Pointer arithmetic to access struct members 17 | *param_1 = lVar3; // I1 Pointer arithmetic to access struct members 18 | *param_2 = 0; // I1 Pointer arithmetic to access struct members 19 | *ppvVar1 = (void *)0x0; // I1 Pointer arithmetic to access struct members 20 | *ppvVar1 = pvVar2; // I1 Pointer arithmetic to access struct members 21 | if ((param_2 != (void *)0x0) && (param_1 != 0)) { // I1 Pointer arithmetic to access struct members 22 | if (*(long *)(lVar3 + 0x20) == 0) { // I1 Pointer arithmetic to access struct members 23 | if (*(long *)(param_1 + 0x10) != 0) { // I1 Pointer arithmetic to access struct members 24 | if (*(long *)(param_1 + 0x18) == 0) { // I1 Pointer arithmetic to access struct members 25 | if (*ppvVar1 == (void *)0x0) { // I1 Pointer arithmetic to access struct members 26 | if (ppvVar1 == (void **)0x0) { // I1 Pointer arithmetic to access struct members 27 | lVar1 = *(long *)(in_FS_OFFSET + 0x28); // I1 Pointer arithmetic to access struct members 28 | p_fclose(*(long *)(param_1 + 0x10)); // I1 Pointer arithmetic to access struct members 29 | param_1[1] = lVar3 + 0x20; // I1 Pointer arithmetic to access struct members 30 | pcVar3 = (char *)0x0; // I1 Pointer arithmetic to access struct members 31 | ppvVar1 = (void **)0x0; // I1 Pointer arithmetic to access struct members 32 | ppvVar1[1] = (void *)0x0; // I1 Pointer arithmetic to access struct members 33 | ppvVar1[1] = param_2; // I1 Pointer arithmetic to access struct members 34 | ppvVar1[2] = (void *)0x0; // I1 Pointer arithmetic to access struct members 35 | puVar1 = (undefined *)list_remove_value(list,test1); // I1 Pointer arithmetic to access struct members 36 | pvVar2 = (void *)ft_memmove(*ppvVar1,param_1,param_2); // I1 Pointer arithmetic to access struct members 37 | pvVar2 = malloc((size_t)param_2); // I1 Pointer arithmetic to access struct members 38 | return (void **)0x0; // I1 Pointer arithmetic to access struct members 39 | iVar1 = getWindowSize(0x4040e8,0x4040ec); // I2 String literal as single integer 40 | ((int)((ulong)(param_2 >> 4) % (lVar4 - 0x10000U >> 0xe)) + 4) * 0x4000 + lVar3; // I2 String literal as single integer 41 | if (*pcRam00000000001010e0 == '\x06') { // I2 String literal as single integer 42 | uVar2 = fz_strlcpy(param_4,&DAT_00100cdf,param_5); // I2 String literal as single integer 43 | __isoc99_scanf(&DAT_00405864,&local_c); // I2 String literal as single integer 44 | interpret_rtl_and(&t0,0x101064,&DAT_0010102c); // I2 String literal as single integer 45 | E._0_4_ = 0; // I2 String literal as single integer 46 | E._4_4_ = 0; // I2 String literal as single integer 47 | E._16_4_ = 0; // I2 String literal as single integer 48 | printf(&DAT_00405fb0); // I2 String literal as single integer 49 | char *pcVar3; // I4 Extraneous variable 50 | char cVar1; // I4 Extraneous variable 51 | char cVar2; // I4 Extraneous variable 52 | int *piVar2; // I4 Extraneous variable 53 | int iVar1; // I4 Extraneous variable 54 | long in_FS_OFFSET; // I4 Extraneous variable 55 | long lVar1; // I4 Extraneous variable 56 | long lVar4; // I4 Extraneous variable 57 | undefined *puVar1; // I4 Extraneous variable 58 | undefined4 uVar2; // I4 Extraneous variable 59 | undefined8 uVar1; // I4 Extraneous variable 60 | undefined8 uVar2; // I4 Extraneous variable 61 | ushort **ppuVar1; // I4 Extraneous variable 62 | void *pvVar2; // I4 Extraneous variable 63 | int iVar1; // I4 Extraneous variable. 64 | piVar2 = __errno_location(); // I6 Expanded standard symbol 65 | piVar2 = __errno_location(); // I6 Expanded standard symbol 66 | ppvVar1 = (void **)malloc(0x18); // I6 Expanded standard symbol 67 | pvVar1 = malloc(0x20020); // I6 Expanded standard symbol 68 | y_FreeUnit(txtsBlock,param_1); // I6 Expanded standard symbol 69 | cVar1 = CheckBaseObject(param_1,7); // I6 Expanded user-defined macro 70 | lVar3 = memory_region(0x83); // I6 Expanded user-defined macro 71 | lVar4 = memory_region_length(0x83); // I6 Expanded user-defined macro 72 | uVar1 = exitError(param_1,param_2,3,0xffffffd5); // I6 Expanded user-defined macro 73 | if (((param_2 == 0) || (0x1b5d < param_2)) && ((param_2 < 0x1f41 || (0x1f85 < param_2)))) { // I6 Expanded user-defined macros 74 | if ((cVar1 == '\x01') && (cVar1 = CheckBaseObject(param_2,6), cVar1 == '\x01')) { // I6 Expanded user-defined macros 75 | return 0; // I6 Expanded user-defined macros 76 | TLN_SetLastError(0); // I6 Expanded user-defined macros 77 | rtl_update_ZFSF(&t0,_DAT_0010105c); // I6 String literal as single integer 78 | cpunum_set_reset_line(1,0); // I6 Uses expanded macros 79 | if (cVar2 == '\0') { // I6 Uses expanded macros 80 | return; // I5 Return value for void function 81 | __stack_chk_fail_local(); // I6 Expanded standard symbol 82 | FUN_00016ca0(param_1); // I6 Expanded standard symbol 83 | int in_GS_OFFSET; // I4 Extraneous variable 84 | int iStack_10; // I4 Extraneous variable 85 | iStack_10 = *(int *)(in_GS_OFFSET + 0x14); // I1 Pointer arithmetic to access struct members 86 | if (iStack_10 != *(int *)(in_GS_OFFSET + 0x14)) { // I3 Confused control flow refactoring 87 | __assert_fail // I6 Expanded standard symbol 88 | puVar3 = (undefined4 *)__errno_location(); // I6 Expanded standard symbol 89 | iVar1 = fopen(param_1,&UNK_0005e3e5); // I2 String literal as single integer 90 | puStack_14 = &UNK_0005f01d; // I2 String literal as single integer 91 | fprintf(_stderr,&UNK_0005e408,param_1,uVar3); // I2 String literal as single integer 92 | -------------------------------------------------------------------------------- /variabledependency.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import networkx as nx 4 | from langchain.schema import HumanMessage 5 | from langchain.chat_models import ChatOpenAI 6 | from langchain.prompts import PromptTemplate 7 | import configparser 8 | 9 | CUR_DIR = os.path.dirname(os.path.abspath(__file__)) 10 | CONFIG = os.path.join(CUR_DIR, 'config.ini') 11 | 12 | def load_config(field: str, value: str) -> str: 13 | """Load parameters from config file""" 14 | config = configparser.ConfigParser() 15 | try: 16 | config.read(CONFIG, encoding='utf-8') 17 | return config[field][value] 18 | except KeyError: 19 | print(f"Error: Cannot find [{field}] {value} in config file") 20 | sys.exit(1) 21 | except UnicodeDecodeError: 22 | print(f"Error: Config file encoding issue. Please save config.ini as UTF-8") 23 | sys.exit(1) 24 | 25 | 26 | os.environ["OPENAI_API_BASE"] = load_config('LLM', 'api_base') 27 | os.environ["OPENAI_API_KEY"] = load_config('LLM', 'api_key') 28 | 29 | # Function to generate the control flow graph (CFG) 30 | def generate_cfg(c_code): 31 | cfg = nx.DiGraph() 32 | lines = c_code.split('\n') 33 | current_node = None 34 | 35 | for i, line in enumerate(lines): 36 | line = line.strip() 37 | if line: 38 | cfg.add_node(i, code=line, type='statement') # Add code information to node attributes 39 | if current_node is not None: 40 | cfg.add_edge(current_node, i) 41 | current_node = i 42 | return cfg, lines 43 | 44 | # Compute post-dominators 45 | def compute_post_dominators(cfg): 46 | post_dominators = nx.immediate_dominators(cfg.reverse(), list(cfg.nodes)[-1]) 47 | return post_dominators 48 | 49 | # Generate control dependence subgraph 50 | def generate_control_dependence_subgraph(cfg, post_dominators): 51 | cdg = nx.DiGraph() 52 | for node in cfg.nodes: 53 | for succ in cfg.successors(node): 54 | if post_dominators[succ] != node: 55 | cdg.add_edge(node, succ, type='control_dependence') 56 | return cdg 57 | 58 | # Generate data dependence subgraph 59 | def generate_data_dependence_subgraph(lines): 60 | ddg = nx.DiGraph() 61 | var_def = {} 62 | 63 | valid_variable_pattern = re.compile(r'^[a-zA-Z_]\w*$') 64 | 65 | for i, line in enumerate(lines): 66 | line = line.strip() 67 | if not line: 68 | continue 69 | 70 | if '=' in line: 71 | var, expr = line.split('=', 1) 72 | var, expr = var.strip(), expr.strip() 73 | ddg.add_node(i, code=line, type='assignment') # Add code information to node attributes 74 | var_names = extract_variables(var) 75 | for var_name in var_names: 76 | if valid_variable_pattern.match(var_name): 77 | ddg.add_node(var_name, type='variable') 78 | ddg.add_edge(i, var_name, type='data_dependence') 79 | var_def[var_name] = i 80 | else: 81 | ddg.add_node(i, code=line, type='statement') # Add code information to node attributes 82 | for var in var_def: 83 | if var in line and valid_variable_pattern.match(var): 84 | ddg.add_edge(var_def[var], i, type='data_dependence') 85 | return ddg 86 | 87 | # Extract all variables from expressions 88 | def extract_variables(expression): 89 | return re.findall(r'\b\w+\b', expression) 90 | 91 | # Extract variable definitions from C code 92 | def extract_variable_definitions(c_code): 93 | variable_pattern = re.compile(r'\b(?:\w+\s+)+(?:\*+\s*)?(\w+)(?:\[\d*\])?\s*;') 94 | keywords = {"return", "goto", "if", "else", "while", "for", "sizeof", "switch", "case", "break", "continue"} 95 | matches = variable_pattern.findall(c_code) 96 | return [match for match in matches if match not in keywords] 97 | 98 | # Generate the PDG 99 | def generate_pdg(c_code): 100 | cfg, lines = generate_cfg(c_code) 101 | post_dominators = compute_post_dominators(cfg) 102 | cdg = generate_control_dependence_subgraph(cfg, post_dominators) 103 | ddg = generate_data_dependence_subgraph(lines) 104 | 105 | pdg = nx.compose(cdg, ddg) 106 | return pdg, lines 107 | 108 | # Find variable dependencies 109 | def find_variable_dependencies(pdg, variable_name, lines): 110 | dependencies = set() 111 | dep_info = [] 112 | 113 | def recursive_find(var_name): 114 | for node, data in pdg.nodes(data=True): 115 | if isinstance(node, str) and node == var_name: 116 | for pred in pdg.predecessors(node): 117 | if pred not in dependencies: 118 | dependencies.add(pred) 119 | if isinstance(pred, int): 120 | expr = lines[pred].split('=', 1)[1].strip() if '=' in lines[pred] else '' 121 | dep_info.append(lines[pred]) 122 | vars_in_expr = extract_variables(expr) 123 | for var in vars_in_expr: 124 | if var != var_name: # Avoid circular dependencies 125 | recursive_find(var) 126 | 127 | recursive_find(variable_name) 128 | return dep_info 129 | 130 | # Generate the prompt template 131 | def create_variable_template(): 132 | template = """ 133 | As a program analysis expert, you possess excellent program analysis skills. Below are the variable dependencies extracted from decompiled code. During the decompilation process, new variables are defined due to register usage, which leads to a large number of redundant variables compared to the all_source_code code. Redundant variables refer to those that are temporary, intermediate, or represent the same data. These variables are often generated during the decompilation process due to register operations or temporary storage needs. Considering temporary or intermediate calculation results, these variables are only used for intermediate steps in computations or operations and are not utilized multiple times or have no significant independent meaning. Repetitively, these variables store the same or similar information and can logically be merged with other statements. The task is to directly output potentially redundant variables without any explanation. The output format is as follows: 134 | **Potential redundant variables:** {all_vars}. 135 | Question: {question} 136 | Helpful Answer: 137 | """ 138 | return PromptTemplate.from_template(template) 139 | 140 | # Format prompt with all dependencies 141 | def format_prompt(all_dependencies): 142 | prompt_template = create_variable_template() 143 | question = "Dependencies for all variables:\n" + "\n".join(all_dependencies) 144 | return prompt_template.format(all_vars="All variables", question=question) 145 | 146 | # Function to call the OpenAI LLM (ChatGPT) 147 | def call_llm(prompt): 148 | llm = ChatOpenAI(model='gpt-4o', temperature=0.5) 149 | response = llm([HumanMessage(content=prompt)]) 150 | return response.content 151 | 152 | def generate_and_query_llm(c_code): 153 | """ 154 | 155 | """ 156 | pdg, lines = generate_pdg(c_code) 157 | 158 | 159 | all_vars = set(extract_variable_definitions(c_code)) 160 | 161 | 162 | all_dependencies = [] 163 | for var in sorted(all_vars): 164 | dependencies = find_variable_dependencies(pdg, var, lines) 165 | if dependencies: 166 | all_dependencies.append(f"\nDependencies for variable '{var}':\n" + "\n".join(dependencies)) 167 | 168 | 169 | if all_dependencies: 170 | prompt = format_prompt(all_dependencies) 171 | # print("\nGenerated Prompt:\n", prompt) 172 | 173 | 174 | response = call_llm(prompt) 175 | return response 176 | 177 | 178 | if __name__ == "__main__": 179 | main() 180 | -------------------------------------------------------------------------------- /pattern_matcher.py: -------------------------------------------------------------------------------- 1 | import re 2 | import random 3 | 4 | 5 | def analyze_fidelity_file(file_path): 6 | """ 7 | Analyze the fidelity_new. c and calculate the proportion of various syntax types 8 | """ 9 | try: 10 | with open(file_path, 'r', encoding='utf-8') as file: 11 | content = file.read() 12 | except FileNotFoundError: 13 | print(f"Warning: Cannot find file {file_path}, using default weights") 14 | return get_default_weights() 15 | 16 | 17 | lines = [] 18 | for line in content.split('\n'): 19 | 20 | if '//' in line: 21 | line = line.split('//')[0] 22 | 23 | line = re.sub(r'/\*.*?\*/', '', line) 24 | line = line.strip() 25 | if line and line not in ['{', '}']: 26 | lines.append(line) 27 | 28 | 29 | type_counts = { 30 | 'assignment': 0, 31 | 'addition': 0, 32 | 'variable': 0, 33 | 'return': 0, 34 | 'loop': 0, 35 | 'conditional': 0, 36 | 'function': 0, 37 | '_TYPE': 0 38 | } 39 | 40 | for line in lines: 41 | 42 | if '=' in line and not any(keyword in line for keyword in ['for', 'while']): 43 | type_counts['assignment'] += 1 44 | 45 | if '+' in line: 46 | type_counts['addition'] += 1 47 | 48 | if re.search(r'\bint\b|\blong\b|\bchar\b|\bWORD\b|\bBYTE\b|\bvoid\b', line): 49 | type_counts['variable'] += 1 50 | 51 | if 'return' in line: 52 | type_counts['return'] += 1 53 | 54 | if 'for' in line or 'while' in line: 55 | type_counts['loop'] += 1 56 | 57 | if 'if' in line or 'else' in line: 58 | type_counts['conditional'] += 1 59 | 60 | if re.search(r'\w+\s*\(.*\)', line): 61 | type_counts['function'] += 1 62 | 63 | keywords = [r'\(_DWORD\b', r'\(_BYTE\b', r'\(_QWORD\b'] 64 | if any(re.search(keyword, line) for keyword in keywords): 65 | type_counts['_TYPE'] += 1 66 | 67 | 68 | total_count = sum(type_counts.values()) 69 | 70 | if total_count == 0: 71 | print("Warning: No syntax type found in the file, using default weights") 72 | return get_default_weights() 73 | 74 | 75 | weights = {} 76 | for type_name, count in type_counts.items(): 77 | ratio = count / total_count 78 | 79 | weight = max(10, min(50, int(ratio * 100 + 10))) 80 | weights[type_name] = weight 81 | 82 | 83 | return weights 84 | 85 | 86 | def get_default_weights(): 87 | """ 88 | Return default weights 89 | """ 90 | return { 91 | 'assignment': 20, 92 | 'addition': 25, 93 | 'variable': 26, 94 | 'return': 25, 95 | 'loop': 25, 96 | 'conditional': 25, 97 | 'function': 20, 98 | '_TYPE': 26 99 | } 100 | 101 | 102 | def calculate_max_semantic_strength(line, weights): 103 | """ 104 | Calculate semantic strength based on dynamic weights 105 | """ 106 | strengths = [] 107 | 108 | 109 | if '=' in line and not any(keyword in line for keyword in ['for', 'while']): 110 | strengths.append(('assignment', weights['assignment'])) 111 | if '+' in line: 112 | strengths.append(('addition', weights['addition'])) 113 | if re.search(r'\bint\b|\blong\b|\bchar\b|\bWORD\b|\bBYTE\b|\bvoid\b', line): 114 | strengths.append(('variable', weights['variable'])) 115 | if 'return' in line: 116 | strengths.append(('return', weights['return'])) 117 | if 'for' in line or 'while' in line: 118 | strengths.append(('loop', weights['loop'])) 119 | if 'if' in line or 'else' in line: 120 | strengths.append(('conditional', weights['conditional'])) 121 | if re.search(r'\w+\s*\(.*\)', line): 122 | strengths.append(('function', weights['function'])) 123 | 124 | 125 | keywords = [r'\(_DWORD\b', r'\(_BYTE\b', r'\(_QWORD\b'] 126 | if any(re.search(keyword, line) for keyword in keywords): 127 | strengths.append(('_TYPE', weights['_TYPE'])) 128 | 129 | return max(strengths, key=lambda x: x[1]) if strengths else (None, 0) 130 | 131 | 132 | def match_patterns(query_lines, fidelity_file_path='fidelity_new.c'): 133 | """ 134 | According to the dynamic weight matching mode 135 | """ 136 | # Analyze the fidelity_new. c file to obtain weights 137 | weights = analyze_fidelity_file(fidelity_file_path) 138 | 139 | 140 | relevant_lines = [line for line in query_lines[1:] if line.strip() and line.strip() not in ['{', '}']] 141 | 142 | 143 | line_strengths = [(line, *calculate_max_semantic_strength(line, weights)) for line in relevant_lines] 144 | 145 | 146 | 147 | 148 | line_strengths.sort(key=lambda x: x[2], reverse=True) 149 | 150 | 151 | total_lines = len(relevant_lines) 152 | if total_lines <= 5: 153 | output_lines = total_lines 154 | else: 155 | output_lines = min(5 + (total_lines - 5) // 9, 10) 156 | 157 | 158 | print(f"Total lines: {total_lines}") 159 | print(f"Output lines: {output_lines}") 160 | 161 | # Select the highest scoring row for each type 162 | selected_lines = [] 163 | seen_types = set() 164 | 165 | 166 | for line, line_type, strength in line_strengths: 167 | if line_type and line_type not in seen_types: 168 | selected_lines.append(line) 169 | seen_types.add(line_type) 170 | if len(selected_lines) == output_lines: 171 | break 172 | 173 | 174 | if len(selected_lines) < output_lines: 175 | for line, line_type, strength in line_strengths: 176 | if line not in selected_lines: 177 | selected_lines.append(line) 178 | if len(selected_lines) == output_lines: 179 | break 180 | 181 | 182 | remaining_types = {'assignment', 'addition', 'variable', 'return', 'loop', 'conditional', 'function', 183 | '_TYPE'} - seen_types 184 | if remaining_types: 185 | for line, line_type, strength in line_strengths: 186 | if line_type in remaining_types: 187 | selected_lines.append(line) 188 | remaining_types.remove(line_type) 189 | if not remaining_types: 190 | break 191 | 192 | return selected_lines 193 | 194 | 195 | def select_random_lines(query_lines): 196 | """ 197 | Randomly select 6 lines from the code as the reference group. 198 | """ 199 | 200 | relevant_lines = [line for line in query_lines[1:] if line.strip() and line.strip() not in ['{', '}']] 201 | 202 | 203 | if len(relevant_lines) < 6: 204 | return relevant_lines 205 | 206 | 207 | random_lines = random.sample(relevant_lines, 6) 208 | return random_lines 209 | 210 | 211 | 212 | if __name__ == "__main__": 213 | # Example 214 | code_input = """ 215 | __fastcall binarySearch(__int64 a1, unsigned int a2, unsigned int a3, unsigned int a4) 216 | { 217 | __int64 result; 218 | unsigned int v5; // I4 219 | if ( (int)a3 < (int)a4 ) 220 | { 221 | v5 = (int)(a4 - 1) / 2 + a3; // I3 222 | if ( a2 == *(_DWORD *)(4LL * (int)v5 + a1) ) // I1 223 | { 224 | result = v5 + 1; // I3 225 | } 226 | else if ( (signed int)a2 >= *(_DWORD *)(4LL * (int)v5 + a1) ) // I1 227 | { 228 | result = binarySearch(a1, a2, v5 + 1, a4); 229 | } 230 | else 231 | { 232 | result = binarySearch(a1, a2, a3, v5 - 1); 233 | } 234 | } 235 | else if ( (signed int)a2 <= *(_DWORD *)(4LL * (int)a3 + a1) ) // I1 236 | { 237 | result = a3; 238 | } 239 | else 240 | { 241 | result = a3 + 1; // I3 242 | } 243 | return result; 244 | } 245 | """ 246 | 247 | 248 | query_lines = code_input.strip().split('\n') 249 | 250 | 251 | selected_lines = match_patterns(query_lines) 252 | 253 | 254 | print("\nSelected lines: ") 255 | for line in selected_lines: 256 | print(line) -------------------------------------------------------------------------------- /testdata/test.txt: -------------------------------------------------------------------------------- 1 | __fastcall decode(_WORD *a1, _BYTE *a2, unsigned __int64 a3) 2 | { 3 | _BYTE *v3; 4 | int v4; 5 | char v5; 6 | int v6; 7 | _WORD *v7; 8 | unsigned __int64 result; 9 | unsigned __int8 v11; 10 | int v12; 11 | int v13; 12 | unsigned __int64 i; 13 | for ( i = 0LL; ; ++i ) 14 | { 15 | result = i; 16 | if ( i >= a3 ) 17 | break; 18 | v3 = a2++; 19 | v11 = *v3 ^ 0xD5; 20 | if ( (((int)v11 >> 4) & 7) != 0 ) 21 | v4 = 256; 22 | else 23 | v4 = 0; 24 | v12 = v4 + ((unsigned __int8)(16 * v11) | 8); 25 | v5 = 1; 26 | if ( (((int)v11 >> 4) & 7) != 0 ) 27 | v5 = ((int)v11 >> 4) & 7; 28 | v13 = v12 << (v5 - 1); 29 | if ( (v11 & 0x80) != 0 ) 30 | v6 = -v13; 31 | else 32 | LOWORD(v6) = v13; 33 | v7 = a1++; 34 | *v7 = v6; 35 | } 36 | return result; 37 | } 38 | ///// 39 | __fastcall BucketSort(__int64 a1) 40 | { 41 | int v1; 42 | int i; 43 | int j; 44 | int k; 45 | int l; 46 | int m; 47 | int n; 48 | int jj; 49 | int v9; 50 | int v10; 51 | __int64 ii; 52 | _QWORD *v12; 53 | _QWORD *v13; 54 | void *ptr; 55 | _QWORD *v15; 56 | v13 = malloc(0x28uLL); 57 | for ( i = 0; i <= 4; ++i ) 58 | v13[i] = 0LL; 59 | for ( j = 0; j <= 7; ++j ) 60 | { 61 | v10 = getBucketIndex(*(_DWORD *)(4LL * j + a1)); 62 | v15 = malloc(0x10uLL); 63 | *(_DWORD *)v15 = *(_DWORD *)(4LL * j + a1); 64 | v15[1] = v13[v10]; 65 | v13[v10] = v15; 66 | } 67 | for ( k = 0; k <= 4; ++k ) 68 | { 69 | printf("Bucket[\"%d\"] : ", (unsigned int)k); 70 | printBuckets((unsigned int *)v13[k]); 71 | putchar(10); 72 | } 73 | for ( l = 0; l <= 4; ++l ) 74 | v13[l] = InsertionSort(v13[l]); 75 | puts("--------------"); 76 | puts("Buckets after sorted"); 77 | for ( m = 0; m <= 4; ++m ) 78 | { 79 | printf("Bucket[\"%d\"] : ", (unsigned int)m); 80 | printBuckets((unsigned int *)v13[m]); 81 | putchar(10); 82 | } 83 | v9 = 0; 84 | for ( n = 0; n <= 4; ++n ) 85 | { 86 | for ( ii = v13[n]; ii; ii = *(_QWORD *)(ii + 8) ) 87 | { 88 | if ( v9 > 7 ) 89 | __assert_fail("j < NARRAY", "github/C-master/sorting/bucket_sort", 0x53u, "BucketSort"); 90 | v1 = v9++; 91 | *(_DWORD *)(a1 + 4LL * v1) = *(_DWORD *)ii; 92 | } 93 | } 94 | for ( jj = 0; jj <= 4; ++jj ) 95 | { 96 | v12 = (_QWORD *)v13[jj]; 97 | while ( v12 ) 98 | { 99 | ptr = v12; 100 | v12 = (_QWORD *)v12[1]; 101 | free(ptr); 102 | } 103 | } 104 | free(v13); 105 | } 106 | ///// 107 | __fastcall printEPS(__int64 a1, unsigned __int64 a2, __int64 a3, int a4) 108 | { 109 | int i; 110 | int k; 111 | double v8; 112 | double v9; 113 | double v10; 114 | double v11; 115 | double v12; 116 | unsigned __int64 j; 117 | unsigned __int64 l; 118 | double v15; 119 | double v16; 120 | double *ptr; 121 | double v18; 122 | v8 = 1.797693134862316e308; 123 | v9 = 2.225073858507201e-308; 124 | v10 = 1.797693134862316e308; 125 | v11 = 2.225073858507201e-308; 126 | ptr = (double *)malloc(24LL * a4); 127 | v18 = (double)a4; 128 | for ( i = 0; i < a4; ++i ) 129 | { 130 | ptr[3 * i] = (double)(3 * (i + 1) % a4) / v18; 131 | ptr[3 * i + 1] = (double)(7 * i % a4) / v18; 132 | ptr[3 * i + 2] = (double)(9 * i % a4) / v18; 133 | } 134 | for ( j = 0LL; j < a2; ++j ) 135 | { 136 | if ( *(double *)(24 * j + a1) > v9 ) 137 | v9 = *(double *)(24 * j + a1); 138 | if ( v8 > *(double *)(24 * j + a1) ) 139 | v8 = *(double *)(24 * j + a1); 140 | if ( *(double *)(24 * j + a1 + 8) > v11 ) 141 | v11 = *(double *)(24 * j + a1 + 8); 142 | if ( v10 > *(double *)(24 * j + a1 + 8) ) 143 | v10 = *(double *)(24 * j + a1 + 8); 144 | } 145 | v12 = (double)400 / (v9 - v8); 146 | if ( v12 > (double)400 / (v11 - v10) ) 147 | v12 = (double)400 / (v11 - v10); 148 | v15 = (v9 + v8) / 2.0; 149 | v16 = (v11 + v10) / 2.0; 150 | printf("%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: -5 -5 %d %d\n", 410LL, 410LL); 151 | puts( 152 | "/l {rlineto} def /m {rmoveto} def\n" 153 | "/c { .25 sub exch .25 sub exch .5 0 360 arc fill } def\n" 154 | "/s { moveto -2 0 m 2 2 l 2 -2 l -2 -2 l closepath \tgsave 1 setgray fill grestore gsave 3 setlinewidth 1 setgray str" 155 | "oke grestore 0 setgray stroke }def"); 156 | for ( k = 0; k < a4; ++k ) 157 | { 158 | printf("%g %g %g setrgbcolor\n", ptr[3 * k], ptr[3 * k + 1], ptr[3 * k + 2]); 159 | for ( l = 0LL; l < a2; ++l ) 160 | { 161 | if ( k == *(_DWORD *)(24 * l + a1 + 16) ) 162 | printf( 163 | "%.3f %.3f c\n", 164 | (double)200 + (*(double *)(24 * l + a1) - v15) * v12, 165 | (*(double *)(24 * l + a1 + 8) - v16) * v12 + (double)200); 166 | } 167 | printf( 168 | "\n0 setgray %g %g s\n", 169 | (double)200 + (*(double *)(24LL * k + a3) - v15) * v12, 170 | (*(double *)(24LL * k + a3 + 8) - v16) * v12 + (double)200); 171 | } 172 | printf("\n%%%%EOF"); 173 | free(ptr); 174 | } 175 | ///// 176 | __fastcall kohonen_update_weights(__int64 a1, __int64 a2, __int64 a3, int a4, int a5, int a6, double a7) 177 | { 178 | int v8; 179 | int v9; 180 | int v10; 181 | int v11; 182 | int v12; 183 | int v13; 184 | double *v14; 185 | int v15; 186 | unsigned int v16; 187 | int v17; 188 | int v18; 189 | int v19; 190 | int v20; 191 | int v21; 192 | int v22; 193 | int v23; 194 | int v24; 195 | int v25; 196 | int v26; 197 | int v31; 198 | unsigned int v35; 199 | int v36; 200 | int i; 201 | int j; 202 | int v39; 203 | int v40; 204 | int v41; 205 | int v42; 206 | int v43; 207 | int v44; 208 | __int64 v45; 209 | double *v46; 210 | double v47; 211 | double v48; 212 | double *v49; 213 | unsigned __int64 v50; 214 | v31 = a4; 215 | v50 = __readfsqword(0x28u); 216 | v45 = 0LL; 217 | v8 = omp_get_num_threads(); 218 | v9 = omp_get_thread_num(); 219 | v10 = a4 / v8; 220 | v11 = a4 % v8; 221 | if ( v9 < a4 % v8 ) 222 | { 223 | v11 = 0; 224 | ++v10; 225 | } 226 | v12 = v10 * v9 + v11; 227 | v13 = v12 + v10; 228 | if ( v12 < v12 + v10 ) 229 | { 230 | v39 = v12; 231 | do 232 | { 233 | for ( i = 0; i < v31; ++i ) 234 | { 235 | *(_QWORD *)(8LL * i + *(_QWORD *)(8LL * v39 + a3)) = 0LL; 236 | for ( j = 0; j < a5; ++j ) 237 | { 238 | v46 = (double *)kohonen_data_3d(a2, v39, i, j); 239 | *(double *)(8LL * i + *(_QWORD *)(8LL * v39 + a3)) = (*v46 - *(double *)(8LL * j + a1)) 240 | * (*v46 - *(double *)(8LL * j + a1)) 241 | + *(double *)(8LL * i + *(_QWORD *)(8LL * v39 + a3)); 242 | } 243 | v14 = (double *)(*(_QWORD *)(8LL * v39 + a3) + 8LL * i); 244 | *v14 = sqrt(*v14); 245 | } 246 | ++v39; 247 | } 248 | while ( v39 < v13 ); 249 | } 250 | GOMP_barrier(); 251 | get_min_2d(a3, v31, (double *)&v45, &v35, &v36); 252 | v15 = v35 - a6; 253 | if ( (int)(v35 - a6) < 0 ) 254 | v15 = 0; 255 | v41 = v15; 256 | if ( v31 <= (int)(v35 + a6) ) 257 | v16 = v31; 258 | else 259 | v16 = v35 + a6 + 1; 260 | v42 = v16; 261 | v17 = v36 - a6; 262 | if ( v36 - a6 < 0 ) 263 | v17 = 0; 264 | v43 = v17; 265 | if ( v31 <= v36 + a6 ) 266 | v18 = v31; 267 | else 268 | v18 = v36 + a6 + 1; 269 | v44 = v18; 270 | v19 = v41; 271 | v20 = v42; 272 | v21 = omp_get_num_threads(); 273 | v22 = omp_get_thread_num(); 274 | v23 = (v20 - v19) / v21; 275 | v24 = (v20 - v19) % v21; 276 | if ( v22 < v24 ) 277 | { 278 | v24 = 0; 279 | ++v23; 280 | } 281 | v25 = v23 * v22 + v24; 282 | if ( v25 < v25 + v23 ) 283 | { 284 | v40 = v19 + v25; 285 | v26 = v25 + v23 + v19; 286 | do 287 | { 288 | for ( i = v43; i < v44; ++i ) 289 | { 290 | v47 = (double)(int)((v35 - v40) * (v35 - v40) + (v36 - i) * (v36 - i)); 291 | v48 = exp(-v47 / ((a7 + a7) * a7)); 292 | for ( j = 0; j < a5; ++j ) 293 | { 294 | v49 = (double *)kohonen_data_3d(a2, v40, i, j); 295 | *v49 = (*(double *)(8LL * j + a1) - *v49) * (a7 * v48) + *v49; 296 | } 297 | } 298 | ++v40; 299 | } 300 | while ( v40 < v26 ); 301 | } 302 | GOMP_barrier(); 303 | return __readfsqword(0x28u) ^ v50; 304 | } -------------------------------------------------------------------------------- /FidelityGPT.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import configparser 4 | from typing import List 5 | from document_processor import ( 6 | load_document, 7 | split_document, 8 | read_queries, 9 | write_output 10 | ) 11 | from pattern_matcher import match_patterns 12 | from embedding_retriever import ( 13 | create_embedding, 14 | create_vectorstore, 15 | create_retriever, 16 | retrieve_documents, 17 | ) 18 | from prompt_templates import ( 19 | create_RAG_prompt_template, 20 | create_RAG_promptwithvariable_template 21 | ) 22 | from langchain_core.runnables import RunnablePassthrough 23 | from langchain_core.output_parsers import StrOutputParser 24 | from langchain_openai import ChatOpenAI 25 | import variabledependency 26 | 27 | # Get current directory and config file path 28 | CUR_DIR = os.path.dirname(os.path.abspath(__file__)) 29 | CONFIG = os.path.join(CUR_DIR, "config.ini") 30 | 31 | 32 | def load_config(field: str, value: str) -> str: 33 | """Load parameters from config file""" 34 | config = configparser.ConfigParser() 35 | try: 36 | config.read(CONFIG, encoding='utf-8') 37 | return config[field][value] 38 | except KeyError: 39 | print(f"Error: Cannot find [{field}] {value} in config file") 40 | sys.exit(1) 41 | except UnicodeDecodeError: 42 | print(f"Error: Config file encoding issue. Please save config.ini as UTF-8") 43 | sys.exit(1) 44 | 45 | 46 | # Set OpenAI environment variables 47 | os.environ["OPENAI_API_BASE"] = load_config("LLM", "api_base") 48 | os.environ["OPENAI_API_KEY"] = load_config("LLM", "api_key") 49 | 50 | 51 | def format_docs(docs: List[str]) -> str: 52 | """Format document list to string""" 53 | return "\n\n".join(docs) 54 | 55 | 56 | def append_to_retrieve_log(file_path: str, sub_query: str, context: str): 57 | """Append retrieval log to file""" 58 | try: 59 | with open(file_path, "a", encoding="utf-8") as f: 60 | f.write(f"Sub-query:\n{sub_query}\n") 61 | f.write(f"Formatted context:\n{context}\n") 62 | f.write("/////\n") 63 | except IOError: 64 | pass 65 | 66 | 67 | def split_into_blocks(lines: List[str], block_size: int = 50, overlap: int = 5) -> List[List[str]]: 68 | """Split long text into blocks with overlap support""" 69 | blocks = [] 70 | total_lines = len(lines) 71 | 72 | start = 0 73 | while start < total_lines: 74 | end = min(start + block_size, total_lines) 75 | block = lines[start:end] 76 | blocks.append(block) 77 | start += block_size - overlap 78 | 79 | return blocks 80 | 81 | 82 | def process_queries( 83 | file_path: str, 84 | output_dir: str, 85 | retriever, 86 | llm, 87 | RAG_prompt, 88 | RAG_prompt_with_variable, 89 | ): 90 | """Process all queries in the file""" 91 | try: 92 | queries = read_queries(file_path) 93 | except Exception: 94 | return 95 | 96 | RAG_results = [] 97 | 98 | for query_index, query in enumerate(queries): 99 | sub_queries = query.strip().split("\n") 100 | query_line_count = len(sub_queries) 101 | 102 | # Decide processing method based on query line count 103 | if query_line_count > 50: 104 | # More than 50 lines, perform variable name extraction and block processing 105 | try: 106 | variable_names = variabledependency.generate_and_query_llm("\n".join(sub_queries)) 107 | except Exception: 108 | variable_names = "" 109 | 110 | # Process queries in blocks 111 | blocks = split_into_blocks(sub_queries) 112 | 113 | for block_index, block in enumerate(blocks): 114 | # Pattern matching 115 | try: 116 | matched_lines = match_patterns(block) 117 | except Exception: 118 | continue 119 | 120 | # Retrieve relevant documents 121 | try: 122 | retrieved_docs = retrieve_documents(retriever, matched_lines) 123 | except Exception: 124 | continue 125 | 126 | # Remove duplicate documents 127 | unique_retrieved_docs = list(dict.fromkeys(retrieved_docs)) 128 | 129 | context = format_docs(unique_retrieved_docs) 130 | 131 | # Log retrieval 132 | append_to_retrieve_log("retrieve-new.txt", "\n".join(block), context) 133 | 134 | # Build variables dictionary 135 | variables = { 136 | "Variable_names": variable_names, 137 | "context": context, 138 | "question": "\n".join(block), 139 | } 140 | 141 | # Build RAG chain 142 | RAG_chain = ( 143 | { 144 | "Variable_names": RunnablePassthrough(), 145 | "context": RunnablePassthrough(), 146 | "question": RunnablePassthrough(), 147 | } 148 | | RAG_prompt_with_variable 149 | | llm 150 | | StrOutputParser() 151 | ) 152 | 153 | # Generate complete prompt and output 154 | full_prompt = RAG_prompt_with_variable.format(**variables) 155 | print(f"\n[Prompt for Query {query_index + 1}, Block {block_index + 1}]:\n{full_prompt}\n") 156 | 157 | # Call model to generate result 158 | try: 159 | RAG_result = RAG_chain.invoke(variables).strip() 160 | RAG_results.append( 161 | f"Query {query_index + 1}, Block {block_index + 1}:\n{RAG_result}\n" 162 | ) 163 | except Exception: 164 | continue 165 | else: 166 | # Less than or equal to 50 lines, process directly 167 | # Pattern matching 168 | try: 169 | matched_lines = match_patterns(sub_queries) 170 | except Exception: 171 | continue 172 | 173 | # Retrieve relevant documents 174 | try: 175 | retrieved_docs = retrieve_documents(retriever, matched_lines) 176 | except Exception: 177 | continue 178 | 179 | # Remove duplicate documents 180 | unique_retrieved_docs = list(dict.fromkeys(retrieved_docs)) 181 | 182 | context = format_docs(unique_retrieved_docs) 183 | 184 | # Log retrieval 185 | append_to_retrieve_log("retrieve-new.txt", "\n".join(matched_lines), context) 186 | 187 | # Build variables dictionary 188 | variables = { 189 | "context": context, 190 | "question": query, 191 | } 192 | 193 | # Build RAG chain 194 | RAG_chain = ( 195 | { 196 | "context": RunnablePassthrough(), 197 | "question": RunnablePassthrough() 198 | } 199 | | RAG_prompt 200 | | llm 201 | | StrOutputParser() 202 | ) 203 | 204 | # Generate complete prompt and output 205 | full_prompt = RAG_prompt.format(**variables) 206 | print(f"\n[Prompt for Query {query_index + 1}]:\n{full_prompt}\n") 207 | 208 | # Call model to generate result 209 | try: 210 | RAG_result = RAG_chain.invoke(variables).strip() 211 | RAG_results.append(f"Query {query_index + 1}:\n{RAG_result}\n") 212 | except Exception: 213 | continue 214 | 215 | # Write results to output file 216 | base_filename = os.path.basename(file_path).split('.')[0] 217 | RAG_output_path = os.path.join(output_dir, f"{base_filename}_RAG_answer.txt") 218 | try: 219 | write_output(RAG_output_path, "\n/////\n".join(RAG_results)) 220 | except Exception: 221 | pass 222 | 223 | 224 | def main(): 225 | """Main function, initialize environment and process files""" 226 | current_dir = os.getcwd() 227 | 228 | # Load paths from config 229 | testdata_dir = os.path.join(current_dir, load_config("PATHS", "input_dir")) 230 | output_dir = os.path.join(current_dir, load_config("PATHS", "output_dir")) 231 | knowledge_base_file = os.path.join(current_dir, load_config("PATHS", "knowledge_base")) 232 | 233 | if not os.path.exists(output_dir): 234 | os.makedirs(output_dir) 235 | 236 | # Load knowledge base 237 | try: 238 | fidelity_content = load_document(knowledge_base_file) 239 | fidelity_documents = split_document(fidelity_content) 240 | fidelity_texts = [doc.page_content for doc in fidelity_documents] 241 | except Exception as e: 242 | print(f"Error loading knowledge base: {e}") 243 | sys.exit(1) 244 | 245 | # Create embeddings and retriever 246 | try: 247 | embeddings = create_embedding(fidelity_texts) 248 | db = create_vectorstore(fidelity_texts, embeddings) 249 | retriever = create_retriever(db) 250 | except Exception as e: 251 | print(f"Error creating embeddings/retriever: {e}") 252 | sys.exit(1) 253 | 254 | # Initialize language model and prompt templates 255 | try: 256 | model_name = load_config("LLM", "model") 257 | temperature = float(load_config("LLM", "temperature")) 258 | llm = ChatOpenAI(model=model_name, temperature=temperature) 259 | RAG_prompt = create_RAG_prompt_template() 260 | RAG_prompt_with_variable = create_RAG_promptwithvariable_template() 261 | except Exception as e: 262 | print(f"Error initializing LLM or prompts: {e}") 263 | sys.exit(1) 264 | 265 | # Process test data 266 | for root, dirs, files in os.walk(testdata_dir): 267 | for file in files: 268 | file_path = os.path.join(root, file) 269 | process_queries(file_path, output_dir, retriever, llm, RAG_prompt, RAG_prompt_with_variable) 270 | 271 | 272 | if __name__ == "__main__": 273 | main() -------------------------------------------------------------------------------- /fidelity_new.c: -------------------------------------------------------------------------------- 1 | v3 = *((_BYTE**)(a1 + 872)); //I1 Pointer arithmetic to access struct references 2 | v3[1] = a2; //I1 Array access to access struct members 3 | v10 = v7(v6, v11, (*((_DWORD*)(a1 + 4))) - v11); //I1 Pointer arithmetic to access struct members 4 | ++(*((_DWORD*)(a1 + 16))); //I1 Pointer arithmetic to access struct members 5 | result = bsplitcb(a1, *(*((_BYTE**)(a2 + 8))), a3, a4, a5); //I1 Pointer arithmetic to access struct members 6 | *((_DWORD*)(result + 4)) = a2; //I1 Pointer arithmetic to access struct members 7 | if ((a2 < 0) || (a2 >= (*((_DWORD*)(a1 + 20))))) //I1 Pointer arithmetic to access struct members 8 | if (!((_DWORD)result)) //I1 Pointer arithemtic to access struct members 9 | free(*((void**)(a1 + 16))); //I1 Pointer arithmetic to access struct members 10 | *((double*)((a1 + (280LL * v5)) + 272)) = a3; //I1 Pointer arithmetic to access array members, Pointer arithmetic to access struct members 11 | *((_DWORD*)(a1 + 12)) = 0; //I1 Pointer arithmetic to access struct members 12 | if (!(*((_DWORD*)(a2 + 44)))) //I1 Pointer arithmetic to access struct members 13 | i += *((_DWORD*)(a2 + 4)); //I1 Pointer arithmetic to access struct members 14 | for (i = 0; i < (*((_DWORD*)(a1 + 16))); ++i) //I1 Pointer arithmetic to access struct members 15 | if ((a1[5] < 0) || (a1[5] > a1[4])) //I1 Array access to access struct members 16 | v11 = v9 - ((unsigned long long) (*((unsigned int*)(a2 + 20)))); //I1 Pointer arithmetic to access struct members 17 | if (*((_QWORD*)(v2 + 32))) //I1 Pointer arithmetic to access struct members 18 | result = *((signed short*)(((*((_QWORD*)(a2 + 8))) + (120LL * (a1 >> 3))) + 52)); //I1 Pointer arithmetic to access struct members, Pointer dereference to access array members 19 | p_free(*((_QWORD*)(a1 + 24))); //I1 Pointer arithmetic to access struct members 20 | v3[1] = 0LL; //I1 Array access to access struct members 21 | *((_DWORD*)((*((_QWORD*)a2)) + 28LL)) = 6; //I1 Pointer dereference to access struct member 22 | for (j = a3; j < (*((_DWORD*)(a1 + 4))); ++j) //I1 Pointer arithmetic to access struct members 23 | *((_QWORD*)(i + 64)) = *((_QWORD*)((*((_QWORD*)(i + 64))) + 64LL)); //I1 Pointer arithmetic to access struct members 24 | v12 = *((_DWORD*)(a2 + 32)); //I1 Pointer arithmetic to access struct members 25 | v5 = (*((_DWORD*)(a1 + 4480)))++; //I1 Pointer arithmetic to access struct members 26 | *((_QWORD*)((*((_QWORD*)(a1 + 32))) + 64LL)) = a2; //I1 Pointer arithmetic to access struct members 27 | *v3 = malloc(a2); //I1 Pointer dereference to access first struct member 28 | v1[2] = 0; //I1 Array access to access struct members 29 | if ((a1[4] <= 7) || (a1[4] > 128)) //I1 Array access to access struct members 30 | return *((_QWORD*)((*((_QWORD*)(a1 + 24))) + (8LL * ((*((_DWORD*)(a1 + 8))) + a2)))); //I1 Pointer arithmetic to access struct members 31 | *v3 = ft_memmove(*v3, a1, a2); //I1 Pointer dereference to access first struct member 32 | result = *((unsigned int*)(*a1)); //I1 Pointer dereference to access first struct member 33 | *a1 = v2; //I1 Pointer dereference to access first struct member 34 | *((_DWORD*)((280LL * v5) + a1)) = 6579570; //I1 Pointer arithmetic to access struct members 35 | v0[12] = 0LL; //I1 Array access to access struct members 36 | ptr = *((void***)(a1 + 8)); //I1 Pointer arithmetic as struct dereference 37 | --(*((_DWORD*)(*a1))); //I1 Pointer dereference to access first struct member 38 | if (!memcmp(*((const void**)(a2 + 8)), (const void*)(i + (*((_QWORD*)(a1 + 8)))), *((signed int*)(a2 + 4)))) //I1 Pointer arithmetic to access struct members 39 | return (*((_QWORD*)a2)) + (8LL * (v7 - (*((_DWORD*)(a2 + 28))))); //I1 Pointer arithmetic to access struct members 40 | *((_BYTE*)((i - 1LL) + a2)) = 0; //I1 Pointer arithmetic to access array members, Character literals as integers 41 | if ((((a3 + a4) > (*((_DWORD*)(a2 + 8)))) || (a4 > (*((_DWORD*)(a2 + 16))))) || (!(*((_QWORD*)a2)))) //I1 Pointer arithmetic to access struct members 42 | result = *((unsigned int*)(a1 + 236)); //I1 Pointer arithmetic to access struct members 43 | *((_DWORD*)(a2 + 28)) = v11; //I1 Pointer arithmetic to access struct members 44 | a1[797] = 0LL; //I1 Array access to access struct members 45 | n = ((unsigned long long) (*((unsigned int*)(a2 + 12)))) << 7; //I1 Pointer arithmetic to access struct members 46 | result = *((_QWORD*)(a1 + 192)); //I1 Pointer arithmetic to access struct members 47 | if (a1[6] >= 0) //I1 Array access to access struct members 48 | a1[796] = malloc(4LL * a2); //I1 Array access to access struct members 49 | a1[1] = v2 + 32; //I1 Array access to access struct members 50 | *(((_BYTE*)v17) + i) ^= *(((_BYTE*)v30) + i); //I1 Pointer arithmetic to access array members 51 | if ((--(*(((_BYTE*)(&z80ex)) + 2))) == 127) //I1 Pointer arithmetic to access struct members 52 | *((_DWORD*)((unsigned int)(a1 + 96))) = result; //I1 Pointer arithemtic to access struct members 53 | if ((*((_DWORD*)(a2 + 4))) == 1) //I1 Pointer arithmetic to access struct members 54 | *(((_BYTE*)v17) + i) = (*(((_BYTE*)v30) + i)) ^ (*(((_BYTE*)v19) + i)); //I1 Pointer arithmetic to access array members 55 | *((_BYTE*)(a1 + 133)) = 1; //I1 Pointer arithmetic to access struct members, Expanded user-defined macros 56 | *((_DWORD*)((4LL * a1) + skns_tilemapA_ram)) = (a3 & (*((_DWORD*)((4LL * a1) + skns_tilemapA_ram)))) | (a2 & (~a3)); //I1 Pointer arithmetic to access array members 57 | ui_text_delete(*((_QWORD*)((8LL * i) + (*((_QWORD*)(a1 + 16)))))); //I1 Pointer arithmetic to access array members 58 | a1[798] = a2; //I1 Array access to access struct members 59 | *(((_BYTE*)v18) + i) ^= *(((_BYTE*)v30) + i); //I1 Pointer arithmetic to access array members 60 | free(*((void**)(((*((_QWORD*)(a1 + 24))) + (136LL * i)) + 112))); //I1 Pointer arithmetic to access struct members 61 | if (*((_DWORD*)(*a1))) //I1 Pointer dereference to access first struct member 62 | result = a2 | (*((_DWORD*)((unsigned int)(a1 + 40)))); //I1 Pointer arithemtic to access struct members 63 | v10 = v9 - (*((_DWORD*)(a2 + 28))); //I1 Pointer arithmetic to access struct members 64 | *v3 = 0LL; //I1 Pointer dereference to access first struct member appears 65 | v13 = v12 - (*((_DWORD*)(a2 + 28))); //I1 Pointer arithmetic to access struct members 66 | if ( *(double *)(24 * j + a1) > v9 ) //I1 Pointer arithmetic to access struct members 67 | v9 = *(double *)(24 * j + a1); //I1 Pointer arithmetic to access struct members 68 | ptr[3 * i] = (double)(3 * (i + 1) % a4) / v18; //I1 Pointer arithmetic to access struct members 69 | *v8 = *a1; //I1 Pointer arithmetic to access struct members 70 | a1[5 * v7 + 6] = a1[1]; //I1 Pointer arithmetic to access struct members 71 | *a1 = -1; //I1 Pointer arithmetic to access struct members 72 | a1[1] = -1; //I1 Pointer arithmetic to access struct members 73 | result = sqlite3CorruptError((int)&loc_10013); //I2 memory address as integers 74 | return 262; //I2 Character literals as integers 75 | if (((*a1) != 47) || (!a1[1])) //I2 Character literals as integers 76 | for (i = *((_QWORD*)(v2 + 16)); *((_QWORD*)(i + 24)); i = *((_QWORD*)(i + 24))) //I2 While loop as non-cannonical for loop 77 | *((_DWORD*)v8) = 538976288; //I2 String literal as single integer 78 | if (((*(*a1)) == 104) || ((result = (unsigned char)(*(*a1)), ((_BYTE)result) == 108))) //I2 Character literal as integer 79 | case 77: //I2 Character literals as integers 80 | *((_QWORD*)v7) = 4702707243111632457LL; //I2 String literal as single integer 81 | case 103: //I2 Character literals as integers 82 | *((_DWORD*)(&optypeTab[strlen(optypeTab)])) = 666749; //I2 String literal as single integer 83 | *((_DWORD*)optypeTab) = 538976288; //I2 String literal as single integer 84 | ERR_GOST_error(129, 111, (int)"gost_pmeth.c", 529); //I2 String literal as single integer 85 | v2 = 63; //I2 String literal as single integer 86 | s[0] = 94; //I2 String literal as single integer 87 | putchar(10); //I2 String literal as single integer 88 | fputc(44, stream); //I2 String literal as single integer 89 | if ( *(_BYTE *)(v2 + a1) == 45 ) //I2 String literal as single integer 90 | return 0LL; //I2 String literal as single integer 91 | if ( v13 == 97 ) //I2 String literal as single integer 92 | v13 = malloc(0x28uLL); //I2 single integer 93 | while ( 1 ) // I3 Confused control flow refactoring 94 | if (a1[796]) //I3 Confused control flow refactoring 95 | if ( (((int)v11 >> 4) & 7) != 0 ) //I3 Confused control flow refactoring 96 | return 8 * ((a1 + 4) / 5); //I3 Confused control flow refactoring 97 | for ( i = (char **)xfts_open(a1, a2, 0); ; v7 = (v7 & process_file((int)i, (int)v9)) != 0 ) //I3 Confused control flow refactoring 98 | if (v2 >= 0 || *_errno_location() == 61) //I3 Confused control flow refactoring 99 | const char* v3; //I4 Extraneous variable 100 | result = *a1; //I4 Extra code to initialize extraneous variable 101 | unsigned int v4; //I4 Extraneous variable 102 | unsigned long long result; //I4 Extraneous variable 103 | v3 = a2; //I4 Extra code to initialize extraneous variable 104 | signed int v3;//I4 Extraneous variable 105 | while (((_BYTE)result) != 13); //I4 Extraneous typecast 106 | v2 = v1; //I4 Extra code to initialize extraneous variable 107 | unsigned int v13; //I4 Extraneous variable 108 | result = a1; //I4 Extra code to initialize extraneous variable 109 | result = v18; //I4 Extra code to initialize extraneous variable 110 | result = (double*)((a1 + (280LL * v5)) + 256); //I1 Array access to access struct members 111 | test_machine_init(*((_QWORD*)(&argc)), argv, envp); //I4 Extra arguments, C3.a. Extraneous typecast 112 | v30 = v17; //I4 Extra code to initialize extraneous variable 113 | v6 = a5; //I4 Extra code to initialize extraneous variable 114 | long long result; //I4 Extraneous variable appears 115 | interpret_rtl_and(&t0, (_DWORD*)0x994, ((_DWORD*)(&operand_write)) + 1); //I4 Global variable issues 116 | * result = a4; //I4 Extra code to initialize extraneous variable 117 | v3 = __errno_location(); //I4 Extraneous code 118 | v4 = strerror(*v3); //I4 Extraneous code 119 | return result; //I5 Return value for void function 120 | return fputs_unlocked(v1, stdout); //I5 Return value for void function 121 | v3 = malloc(8LL * a1); //I6 Expanded standard symbol 122 | v1 = malloc(0x20020uLL); //I6 Expanded standard symbol 123 | v9 = __readgsdword(0x14u); // I6 Expanded standard symbol appears 39 times in retrieve.txt 124 | _assert_fail("image_info != (const ImageInfo *) NULL", "coders/art.c", 0x134u, "WriteARTImage"); // I6 Expanded standard symbol 125 | j_LogMagickEvent((char *)&stru_7FF4.st_info, "MagickCore/blob.c", "DetachBlob", 1035, "..."); // I6 Expanded standard symbol 126 | result = _errno_location(); // I6 Expanded standard symbol 127 | v5[27] = __readgsdword(0x14u); // I6 Expanded standard symbol 128 | BYTE2(v16) ^= BYTE1(v14); // I6 Expanded standard symbol appears 129 | return __readgsdword(0x14u) ^ v9; // I6 Expanded standard symbol 130 | __assert_fail("retkey", "import.c", 0x5A2u, "openssh_new_read"); // I6 Expanded standard symbol 131 | putchar_unlocked(v3); // I6 Expanded standard symbol 132 | fputs_unlocked(ptr, stdout); // I6 Expanded standard symbol 133 | while ( !feof_unlocked(a1) && !ferror_unlocked(a1) && v15 < 0x7800 ); // I6 Expanded standard symbol 134 | if ( ferror_unlocked(a1) ) // I6 Expanded standard symbol 135 | v10 = fwrite_unlocked(ptr, 1u, n, a2); // I6 Expanded standard symbol 136 | return fputc_unlocked(10, (FILE *)stderr); // I6 Expanded standard symbol 137 | LOBYTE(v3) = o_nocache_eof != 0; // I6 Expanded standard symbol 138 | BYTE2(v16) ^= BYTE1(v14); // I6 Expanded standard symbol 139 | LOBYTE(v16) = HIBYTE(v14) ^ v16; // I6 Expanded standard symbol 140 | *a4 = sqlite3CorruptError((int)&loc_1014D); // I6 Expanded standard symbol 141 | sqlite3SelectPrep(s[0], v5, (int)s); // I6 Expanded standard symbol 142 | sqlite3WalkSelect((int)a1, v5); // I6 Expanded standard symbol 143 | c_write(a1, (int)"\b \b", 3); // I6 Expanded standard symbol 144 | v4 = fwrite(ptr, 1u, n, *(FILE **)a1); // I6 Expanded standard symbol 145 | BIO_puts(a1, (int)"subject="); // I6 Expanded standard symbol 146 | v3 = CRYPTO_malloc(v2, (int)"apps.c", 1544); // I6 Expanded standard symbol 147 | ERR_put_error(0xDu, 182, 187, (int)"asn1_gen.c", 399); // I6 Expanded standard symbol 148 | result = CRYPTO_free((int)a1); // I6 Expanded standard symbol 149 | return LODWORD(v5); // I6 Expanded standard symbol 150 | result = j_LogMagickEvent((char *)&stru_7FF4.st_info, "MagickCore/blob.c", "AttachCustomStream", 312, "..."); // I6 Expanded standard symbol -------------------------------------------------------------------------------- /prompt_templates.py: -------------------------------------------------------------------------------- 1 | from langchain.prompts import PromptTemplate 2 | from langchain.schema import SystemMessage, HumanMessage, AIMessage 3 | 4 | 5 | def create_variable_template(): 6 | template = """As a program analysis expert, you possess excellent program analysis skills. Below are the variable dependencies extracted from decompiled code. During the decompilation process, new variables are defined due to register usage, which leads to a large number of redundant variables compared to the source code. Redundant variables refer to those that are temporary, intermediate, or represent the same data. These variables are often generated during the decompilation process due to register operations or temporary storage needs. Considering temporary or intermediate calculation results, these variables are only used for intermediate steps in computations or operations and are not utilized multiple times or have no significant independent meaning. Repetitively, these variables store the same or similar information and can logically be merged with other statements. The task is to directly output potentially redundant variables without any explanation. The output format is as follows: **Potential redundant variable: {all variable names}. 7 | Question: {question} 8 | Helpful Answer: 9 | """ 10 | return PromptTemplate.from_template(template) 11 | def create_prompt_template(): 12 | template = """As an experienced reverse engineering expert, I possess advanced skills in using reverse engineering tools (such as IDA Pro, Ghidra) to analyze program code. 13 | I have extensive expertise in decompiled code analysis, but the readability of decompiled code is often poor, so I must carefully check and verify each line of the decompiled code. Below is the input question: 14 | Question: {question} 15 | The task is to improve the readability of the decompiled code by performing the following operations: 1. Restore meaningful variable names; 2. Restore the original code as much as possible without changing the semantics. 16 | Output all lines of the Question code and add “//fixed” after the corrected lines, without providing any further explanation. 17 | Helpful Answer: 18 | """ 19 | return PromptTemplate.from_template(template) 20 | def create_zero_shot_prompt_template(): 21 | template = """As an experienced reverse engineering expert, I possess advanced skills in using reverse analysis tools (e.g., IDA Pro, Ghidra) to analyze program code. I have extensive expertise in analyzing decompiled code and am capable of accurately identifying false positives and false negatives. It is worth noting that these reverse engineering tools often generate significant code semantic distortions during decompilation due to factors such as the compiler, architecture, and optimization level. Therefore, I must carefully review and verify each line of decompiled code. 22 | I have pre-defined the following types of distortions (i.e., semantic differences between source code and decompiled code): 23 | I1: Non-inertial dereferencing: Involves using pointers or arrays to access structure or array members. I check if decompiled code uses pointers or arrays for structure members (with forced type casts like _DWORD, _BYTE) or pointer access for array members. 24 | I2: Character and string literal issues: Decompilers may replace characters, strings, addresses, or macros with integers. I verify if integers in decompiled code represent these elements. 25 | I3: Obfuscated control flow reconstruction: Involves altered control flow, such as swapped while/for loops, inlined functions, or deconstructed ternary operators. I check for abnormal control flow in decompiled code. 26 | I4: Redundant code: Involves unnecessary variable declarations, meaningless parameter assignments, assigning non-returning function calls to variables, redundant variables from non-inertial dereferencing, or variable assignments from compiler/user macros. This often leads to false negatives and requires careful inspection. 27 | I5: Return exceptions: Function structure or return values deviate from expectations, such as adding meaningless returns. 28 | I6: Use of non-typed symbols: Occurs when decompiled code uses non-typed symbols, user macros, abnormal function calls, or compiler-specific functions. 29 | Please analyze the following decompiled code line by line and consider the potential distortion issues in each line of code. 30 | Input question: 31 | Question: {question} 32 | Output format: 33 | Output: Output all the decompiled code from the problem and append the distortion type number after each line where a distortion is found, without explanation. 34 | Helpful Answer: 35 | """ 36 | return PromptTemplate.from_template(template) 37 | def create_RAG_prompt_template(): 38 | template = """As an experienced reverse engineering expert, I possess advanced skills in analyzing program code using reverse engineering tools such as IDA Pro and Ghidra. I have extensive expertise in analyzing decompiled code and can accurately identify both false positives and false negatives. It is important to note that these reverse engineering tools often produce significant code semantic distortions during the decompilation process due to factors like the compiler, architecture, and optimization levels. Therefore, I must carefully review and verify every line of decompiled code. I have pre-defined the following types of distortions (i.e., semantic discrepancies between the source code and decompiled code): 39 | I1: Non-inertial dereferencing: Involves using pointers or arrays to access structure or array members. I check if decompiled code uses pointers or arrays for structure members (with forced type casts like _DWORD, _BYTE) or pointer access for array members. 40 | I2: Character and string literal issues: Decompilers may replace characters, strings, addresses, or macros with integers. I verify if integers in decompiled code represent these elements. 41 | I3: Obfuscated control flow reconstruction: Involves altered control flow, such as swapped while/for loops, inlined functions, or deconstructed ternary operators. I check for abnormal control flow in decompiled code. 42 | I4: Redundant code: Involves unnecessary variable declarations, meaningless parameter assignments, assigning non-returning function calls to variables, redundant variables from non-inertial dereferencing, or variable assignments from compiler/user macros. This often leads to false negatives and requires careful inspection. 43 | I5: Return exceptions: Function structure or return values deviate from expectations, such as adding meaningless returns. 44 | I6: Use of non-typed symbols: Occurs when decompiled code uses non-typed symbols, user macros, abnormal function calls, or compiler-specific functions. 45 | {context} 46 | Consider the retrieval results from the distorted code database. These retrieval results indicate code lines with high similarity to distortion issues. My responsibility is to analyze the following decompiled code line by line, considering the potential distortion issues in the code. The retrieval results are only for contextual reference and are not to be outputted. 47 | Below is the question input: 48 | Question: {question} 49 | **Requirements**: Only label, do not fix. 50 | **Output format**: Output all decompiled code in the question, and for each identified distorted code line, append the distortion type number with “//Distortion type number” without explanation. 51 | Helpful Answer: 52 | """ 53 | return PromptTemplate.from_template(template) 54 | def create_RAG_promptwithvariable_template(): 55 | template = """As an experienced reverse engineering expert, I possess advanced skills in analyzing program code using reverse engineering tools such as IDA Pro and Ghidra. I have extensive expertise in analyzing decompiled code and can accurately identify both false positives and false negatives. It is important to note that these reverse engineering tools often produce significant code semantic distortions during the decompilation process due to factors like the compiler, architecture, and optimization levels. Therefore, I must carefully review and verify every line of decompiled code. I have pre-defined the following types of distortions (i.e., semantic discrepancies between the source code and decompiled code): 56 | I1: Non-inertial dereferencing: Involves using pointers or arrays to access structure or array members. I check if decompiled code uses pointers or arrays for structure members (with forced type casts like _DWORD, _BYTE) or pointer access for array members. 57 | I2: Character and string literal issues: Decompilers may replace characters, strings, addresses, or macros with integers. I verify if integers in decompiled code represent these elements. 58 | I3: Obfuscated control flow reconstruction: Involves altered control flow, such as swapped while/for loops, inlined functions, or deconstructed ternary operators. I check for abnormal control flow in decompiled code. 59 | I4: Redundant code: Involves unnecessary variable declarations, meaningless parameter assignments, assigning non-returning function calls to variables, redundant variables from non-inertial dereferencing, or variable assignments from compiler/user macros. This often leads to false negatives and requires careful inspection. 60 | I5: Return exceptions: Function structure or return values deviate from expectations, such as adding meaningless returns. 61 | I6: Use of non-typed symbols: Occurs when decompiled code uses non-typed symbols, user macros, abnormal function calls, or compiler-specific functions. 62 | {Variable_names} 63 | First, the function below may be split into blocks. Consider the potential redundant variables above and analyze the decompiled function block. 64 | {context} 65 | Next, consider the retrieval results from the distorted code database. These retrieval results indicate code lines with high similarity to distortion issues. My responsibility is to analyze the following decompiled code line by line, considering the potential distortion issues in the code. The retrieval results are only for contextual reference and are not to be outputted. 66 | Below is the question input: 67 | Question: {question} 68 | **Requirements**: Only label, do not fix. 69 | **Output format**: Output all decompiled code in the question, and for each identified distorted code line, append the distortion type number with “//Distortion type number” without explanation. 70 | Helpful Answer: 71 | """ 72 | return PromptTemplate.from_template(template) 73 | def create_RAG_correction_template(): 74 | template = """As an experienced reverse engineering expert, I possess advanced skills in analyzing program code using reverse engineering tools such as IDA Pro and Ghidra. I have extensive expertise in decompiled code analysis, enabling me to accurately identify false positives and false negatives. It is noteworthy that these reverse engineering tools often generate significant code semantic distortions during the decompilation process due to compiler settings, architecture differences, and optimization levels. Therefore, I must carefully verify every line of the decompiled code. 75 | 76 | I have pre-defined the following types of distortions (i.e., semantic discrepancies between source code and decompiled code): 77 | 78 | - **I1: Non-inertial Dereferencing**: This involves using pointers and arrays to access structure members or accessing array members with pointers. When the source code accesses structure members, but the decompiled code uses pointers or arrays to access structure members (or vice versa for arrays), you need to review and correct the dereferencing method. 79 | - **I2: Character and String Literal Representation Issues**: This occurs when string literals are replaced with references or represented as integers. If the source code uses characters or strings but the decompiled code represents them as references or integers, review and correct the numeric values. 80 | - **I3: Obfuscated Control Flow Reconstruction**: This involves swapping `while` and `for` loops, inline functions, or deconstructing ternary operators. If the control flow in the source code changes in the decompiled code, it needs to be reviewed. 81 | - **I4: Redundant Code**: This includes declaring unnecessary new variables to perform the same function, assigning parameters to variables unnecessarily, assigning variables from function calls without return values, introducing redundant variables due to non-inertial dereferencing, and introducing variables through compiler or user macros. These issues need to be fixed. 82 | - **I5: Return Anomalies**: If the structure or return value of a function is unexpected, it should be corrected. 83 | - **I6: Usage of Non-Type Symbols**: This occurs when the decompiled code uses symbols or macros that do not conform to types. If the same semantic decompiled code uses symbols, user macros, function calls, or compiler-specific functions that are type-inconsistent, corrections are required. 84 | Considering the above, I initially review the retrieval results from the distorted code repository. However, these results represent code lines with a high similarity in distortion issues. Therefore, my responsibility is to analyze each line of the decompiled code individually, taking into account the potential distortion issues in the code. The retrieved results serve only as contextual references but are not to be output. 85 | Here is the problem input: 86 | Question: {question} 87 | You are required to perform the following tasks from the perspective of improving code readability and simplifying the code: 88 | 1. Fix the distortion issues listed above. 89 | 2. Restore meaningful variable names. 90 | 3. Reconstruct the decompiled code to meet deliverable standards. 91 | Output format: 92 | Output: Fix the distortion issues + “//fixed” without further explanation. 93 | Helpful Answer: 94 | """ 95 | return PromptTemplate.from_template(template) 96 | def create_few_shot_prompt_template(): 97 | uva_position_prompt = """As an experienced reverse engineering expert, I possess advanced skills in using reverse analysis tools (e.g., IDA Pro, Ghidra) to analyze program code. I have extensive expertise in analyzing decompiled code and am capable of accurately identifying false positives and false negatives. It is worth noting that these reverse engineering tools often generate significant code semantic distortions during decompilation due to factors such as the compiler, architecture, and optimization level. Therefore, I must carefully review and verify each line of decompiled code. 98 | I have pre-defined the following types of distortions (i.e., semantic differences between source code and decompiled code): 99 | I1: Non-inertial dereferencing: Involves using pointers or arrays to access structure or array members. I check if decompiled code uses pointers or arrays for structure members (with forced type casts like _DWORD, _BYTE) or pointer access for array members. 100 | I2: Character and string literal issues: Decompilers may replace characters, strings, addresses, or macros with integers. I verify if integers in decompiled code represent these elements. 101 | I3: Obfuscated control flow reconstruction: Involves altered control flow, such as swapped while/for loops, inlined functions, or deconstructed ternary operators. I check for abnormal control flow in decompiled code. 102 | I4: Redundant code: Involves unnecessary variable declarations, meaningless parameter assignments, assigning non-returning function calls to variables, redundant variables from non-inertial dereferencing, or variable assignments from compiler/user macros. This often leads to false negatives and requires careful inspection. 103 | I5: Return exceptions: Function structure or return values deviate from expectations, such as adding meaningless returns. 104 | I6: Use of non-typed symbols: Occurs when decompiled code uses non-typed symbols, user macros, abnormal function calls, or compiler-specific functions.""" 105 | 106 | uva_example_q1 = """example 1: 107 | void *__cdecl AES_cbc_encrypt(int a1, int a2, int a3, int a4, void *dest, int a6) 108 | { 109 | void *result; 110 | if ( a6 ) 111 | result = CRYPTO_cbc128_encrypt(a1, a2, a3, a4, dest, (int)AES_encrypt); 112 | else 113 | result = (void *)CRYPTO_cbc128_decrypt( 114 | (int *)a1, 115 | (int *)a2, 116 | a3, 117 | a4, 118 | dest, 119 | (void (__cdecl *)(_DWORD *, int *, int))AES_decrypt); 120 | return result; 121 | } 122 | }""" 123 | 124 | uva_example_a1 = """ 125 | void *__cdecl AES_cbc_encrypt(int a1, int a2, int a3, int a4, void *dest, int a6) 126 | { 127 | void *result; // I4 128 | if ( a6 ) 129 | result = CRYPTO_cbc128_encrypt(a1, a2, a3, a4, dest, (int)AES_encrypt); 130 | else 131 | result = (void *)CRYPTO_cbc128_decrypt( 132 | (int *)a1, // I1 133 | (int *)a2, // I1 134 | a3, 135 | a4, 136 | dest, 137 | (void (__cdecl *)(_DWORD *, int *, int))AES_decrypt); // I1 138 | return result; // I5 139 | } 140 | """ 141 | 142 | uva_example_q2 = """example 2: 143 | __fastcall SetStreamBuffering(int a1, int a2) 144 | { 145 | int v2; 146 | unsigned int n; 147 | const char *v6; 148 | n = 0x4000; 149 | v6 = (const char *)j_GetImageOption(a1, (unsigned int)"stream:buffer-size"); 150 | if ( v6 ) 151 | n = StringToUnsignedLong(v6); 152 | if ( n ) 153 | v2 = 0; 154 | else 155 | v2 = 2; 156 | return setvbuf(*(FILE **)(*(_DWORD *)(a2 + 13128) + 68), 0, v2, n) == 0; 157 | } 158 | """ 159 | 160 | uva_example_a2 = """ 161 | __fastcall SetStreamBuffering(int a1, int a2) 162 | { 163 | int v2; 164 | unsigned int n; 165 | const char *v6; 166 | n = 0x4000; 167 | v6 = (const char *)j_GetImageOption(a1, (unsigned int)"stream:buffer-size"); // I6 168 | if ( v6 ) 169 | n = StringToUnsignedLong(v6); 170 | if ( n ) // I3 171 | v2 = 0; 172 | else 173 | v2 = 2; 174 | return setvbuf(*(FILE **)(*(_DWORD *)(a2 + 13128) + 68), 0, v2, n) == 0; // I1 175 | } 176 | """ 177 | 178 | uva_example_q3 = """example 3: 179 | __fastcall ReadBlobString(int a1, int a2) 180 | { 181 | int i; 182 | int v7; 183 | if ( !a1 ) 184 | _assert_fail("image != (Image *) NULL", "MagickCore/blob.c", 0x12E7u, "ReadBlobString"); 185 | for ( i = 0; i <= 4094; ++i ) 186 | { 187 | *(_BYTE *)(a2 + i) = v7; 188 | if ( v7 == 10 ) 189 | { 190 | if ( i > 0 && *(_BYTE *)(a2 + i - 1) == 13 ) 191 | --i; 192 | break; 193 | } 194 | } 195 | *(_BYTE *)(a2 + i) = 0; 196 | return a2; 197 | } 198 | """ 199 | 200 | uva_example_a3 = """ 201 | __fastcall ReadBlobString(int a1, int a2) 202 | { 203 | int i; 204 | int v7; 205 | if ( !a1 ) 206 | _assert_fail("image != (Image *) NULL", "MagickCore/blob.c", 0x12E7u, "ReadBlobString"); // I6 207 | for ( i = 0; i <= 4094; ++i ) 208 | { 209 | *(_BYTE *)(a2 + i) = v7; // I1 210 | if ( v7 == 10 ) // I2 211 | { 212 | if ( i > 0 && *(_BYTE *)(a2 + i - 1) == 13 ) // I2 213 | --i; 214 | break; 215 | } 216 | } 217 | *(_BYTE *)(a2 + i) = 0; // I1 218 | return a2; 219 | }}""" 220 | 221 | sys_prompt = uva_position_prompt 222 | prompt_list = [ 223 | SystemMessage(content=sys_prompt), 224 | HumanMessage(content=uva_example_q1), 225 | AIMessage(content=uva_example_a1), 226 | HumanMessage(content=uva_example_q2), 227 | AIMessage(content=uva_example_a2), 228 | HumanMessage(content=uva_example_q3), 229 | AIMessage(content=uva_example_a3), 230 | ] 231 | 232 | template = """ 233 | The above are examples of distortion detection. Please refer to the examples and analyze the following decompiled code line by line, considering possible distortion issues in the code. 234 | Please analyze the following decompiled code line by line and consider the potential distortion issues in each line of code. 235 | Input question: 236 | Question: {question} 237 | Output format: 238 | Output: Output all the decompiled code from the problem and append the distortion type number after each line where a distortion is found, without explanation. 239 | Helpful Answer: 240 | """ 241 | prompt_list.append(HumanMessage(content=template)) 242 | 243 | return prompt_list 244 | -------------------------------------------------------------------------------- /Dataset/curl.txt: -------------------------------------------------------------------------------- 1 | __fastcall Curl_resolver_kill(int a1) 2 | { 3 | _DWORD *result; 4 | _DWORD *v2; 5 | v2 = *(_DWORD **)(a1 + 1328); 6 | if ( v2 && *v2 ) 7 | result = (_DWORD *)thread_wait_resolv(a1, 0, 0); 8 | else 9 | result = Curl_resolver_cancel(a1); 10 | return result; 11 | } 12 | ///// 13 | __fastcall destroy_async_data(_DWORD *a1) 14 | { 15 | _DWORD *result; 16 | int v2; 17 | int fd; 18 | int *v4; 19 | int v5; 20 | if ( a1[4] ) 21 | { 22 | v2 = a1[4]; 23 | fd = *(_DWORD *)(v2 + 36); 24 | v4 = *(int **)(v2 + 32); 25 | pthread_mutex_lock(*(pthread_mutex_t **)(v2 + 16)); 26 | v5 = *(_DWORD *)(v2 + 20); 27 | *(_DWORD *)(v2 + 20) = 1; 28 | pthread_mutex_unlock(*(pthread_mutex_t **)(v2 + 16)); 29 | if ( v5 ) 30 | { 31 | if ( *(_DWORD *)v2 ) 32 | Curl_thread_join((pthread_t **)v2); 33 | destroy_thread_sync_data((_DWORD *)(v2 + 16)); 34 | Curl_cfree(a1[4]); 35 | } 36 | else 37 | { 38 | Curl_thread_destroy(*(pthread_t **)v2); 39 | } 40 | if ( v4 ) 41 | Curl_multi_closed(*v4, fd); 42 | close(fd); 43 | } 44 | a1[4] = 0; 45 | Curl_cfree(*a1); 46 | result = a1; 47 | *a1 = 0; 48 | return result; 49 | } 50 | ///// 51 | __fastcall Curl_resolver_getsock(int *a1, _DWORD *a2) 52 | { 53 | int v2; 54 | int v3; 55 | int v5; 56 | int v6; 57 | int *v7; 58 | int v8; 59 | __int64 v9; 60 | __time_t v10[2]; 61 | v5 = 0; 62 | v6 = *a1; 63 | v7 = *(int **)(*a1 + 3380); 64 | v8 = a1[332]; 65 | if ( v8 ) 66 | { 67 | *a2 = *(_DWORD *)(v8 + 36); 68 | *(_DWORD *)(v8 + 32) = a1; 69 | v5 = 1; 70 | } 71 | else 72 | { 73 | Curl_now(v10); 74 | v9 = Curl_timediff(v10[0], v10[1], *v7, v7[1]); 75 | if ( v9 >= 3 ) 76 | { 77 | if ( v9 >= 51 ) 78 | { 79 | if ( v9 >= 251 ) 80 | Curl_expire(v6, v2, 200LL, 1); 81 | else 82 | Curl_expire(v6, v2, 50LL, 1); 83 | } 84 | else 85 | { 86 | Curl_expire(v6, v3, v9 / 3, 1); 87 | } 88 | } 89 | else 90 | { 91 | Curl_expire(v6, v2, 0LL, 1); 92 | } 93 | } 94 | return v5; 95 | } 96 | ///// 97 | __fastcall Curl_resolver_getaddrinfo(int *a1, int a2, int a3, _DWORD *a4) 98 | { 99 | int v4; 100 | int v5; 101 | _DWORD *v6; 102 | __time_t v7; 103 | int v8; 104 | int v9; 105 | __time_t v11[3]; 106 | _DWORD *v12; 107 | int v13; 108 | int *v14; 109 | int v15; 110 | int v16; 111 | _DWORD *v17; 112 | int v18[8]; 113 | v14 = a1; 114 | v13 = a2; 115 | v12 = a4; 116 | v15 = 2; 117 | v16 = *a1; 118 | v17 = *(_DWORD **)(v16 + 3380); 119 | *a4 = 0; 120 | v4 = v14[316]; 121 | if ( v4 == 1 ) 122 | { 123 | v15 = 2; 124 | } 125 | else if ( v4 == 2 ) 126 | { 127 | v15 = 10; 128 | } 129 | else 130 | { 131 | v15 = 0; 132 | } 133 | if ( v15 != 2 && (unsigned __int8)Curl_ipv6works((int)v14) != 1 ) 134 | v15 = 2; 135 | memset(v18, 0, sizeof(v18)); 136 | v18[1] = v15; 137 | if ( v14[190] == 3 ) 138 | v5 = 2; 139 | else 140 | v5 = 1; 141 | v18[2] = v5; 142 | v6 = v17; 143 | Curl_now(v11); 144 | v7 = v11[1]; 145 | *v6 = v11[0]; 146 | v6[1] = v7; 147 | if ( init_resolve_thread((int)v14, v13, a3, v18) ) 148 | *v12 = 1; 149 | else 150 | Curl_failf(v16, "getaddrinfo() thread failed to start\n", v9, v8); 151 | return 0; 152 | } 153 | ///// 154 | __fastcall destroy_thread_sync_data(_DWORD *a1) 155 | { 156 | if ( *a1 ) 157 | { 158 | pthread_mutex_destroy((pthread_mutex_t *)*a1); 159 | Curl_cfree(*a1); 160 | } 161 | Curl_cfree(a1[2]); 162 | if ( a1[8] ) 163 | Curl_freeaddrinfo(a1[8]); 164 | if ( a1[6] != -1 ) 165 | close(a1[6]); 166 | return memset(a1, 0, 0x48u); 167 | } 168 | ///// 169 | __fastcall getaddrinfo_complete(int a1) 170 | { 171 | int result; 172 | int v2; 173 | v2 = conn_thread_sync_data(a1); 174 | result = Curl_addrinfo_callback(a1, *(_DWORD *)(v2 + 28), *(_DWORD *)(v2 + 32)); 175 | *(_DWORD *)(v2 + 32) = 0; 176 | return result; 177 | } 178 | ///// 179 | __fastcall getaddrinfo_thread(int a1) 180 | { 181 | int v1; 182 | int v4; 183 | int v5; 184 | char v6[4]; 185 | char v7[12]; 186 | v4 = *(_DWORD *)(a1 + 68); 187 | curl_msnprintf((int)v7, 12, (int)"%d", *(_DWORD *)(a1 + 12)); 188 | v5 = Curl_getaddrinfo_ex(*(const char **)(a1 + 8), v7, (const struct addrinfo *)(a1 + 36), (_DWORD *)(a1 + 32)); 189 | if ( v5 ) 190 | { 191 | v1 = *_errno_location() ? *_errno_location() : v5; 192 | *(_DWORD *)(a1 + 28) = v1; 193 | if ( !*(_DWORD *)(a1 + 28) ) 194 | *(_DWORD *)(a1 + 28) = -10; 195 | } 196 | pthread_mutex_lock(*(pthread_mutex_t **)a1); 197 | if ( *(_DWORD *)(a1 + 4) ) 198 | { 199 | pthread_mutex_unlock(*(pthread_mutex_t **)a1); 200 | destroy_thread_sync_data((_DWORD *)a1); 201 | Curl_cfree(v4); 202 | } 203 | else 204 | { 205 | if ( *(_DWORD *)(a1 + 24) != -1 ) 206 | { 207 | v6[0] = 1; 208 | if ( send(*(_DWORD *)(a1 + 24), v6, 1u, 0x4000) < 0 ) 209 | *(_DWORD *)(a1 + 28) = *_errno_location(); 210 | } 211 | *(_DWORD *)(a1 + 4) = 1; 212 | pthread_mutex_unlock(*(pthread_mutex_t **)a1); 213 | } 214 | return 0; 215 | } 216 | ///// 217 | __fastcall destroy_async_data(_DWORD *a1) 218 | { 219 | _DWORD *result; 220 | int v2; 221 | int fd; 222 | int *v4; 223 | int v5; 224 | if ( a1[4] ) 225 | { 226 | v2 = a1[4]; 227 | fd = *(_DWORD *)(v2 + 36); 228 | v4 = *(int **)(v2 + 32); 229 | pthread_mutex_lock(*(pthread_mutex_t **)(v2 + 16)); 230 | v5 = *(_DWORD *)(v2 + 20); 231 | *(_DWORD *)(v2 + 20) = 1; 232 | pthread_mutex_unlock(*(pthread_mutex_t **)(v2 + 16)); 233 | if ( v5 ) 234 | { 235 | if ( *(_DWORD *)v2 ) 236 | Curl_thread_join((pthread_t **)v2); 237 | destroy_thread_sync_data((_DWORD *)(v2 + 16)); 238 | Curl_cfree(a1[4]); 239 | } 240 | else 241 | { 242 | Curl_thread_destroy(*(pthread_t **)v2); 243 | } 244 | if ( v4 ) 245 | Curl_multi_closed(*v4, fd); 246 | close(fd); 247 | } 248 | a1[4] = 0; 249 | Curl_cfree(*a1); 250 | result = a1; 251 | *a1 = 0; 252 | return result; 253 | } 254 | ///// 255 | __fastcall init_resolve_thread(int a1, int a2, int a3, _DWORD *a4) 256 | { 257 | int v5; 258 | pthread_t **v6; 259 | v6 = (pthread_t **)Curl_ccalloc(1, 88); 260 | v5 = 12; 261 | *(_DWORD *)(a1 + 1328) = v6; 262 | if ( v6 ) 263 | { 264 | *(_DWORD *)(a1 + 1316) = a3; 265 | *(_BYTE *)(a1 + 1332) &= 0x7Fu; 266 | *(_DWORD *)(a1 + 1324) = 0; 267 | *(_DWORD *)(a1 + 1320) = 0; 268 | *v6 = 0; 269 | if ( init_thread_sync_data((int)v6, a2, a3, a4) ) 270 | { 271 | Curl_cfree(*(_DWORD *)(a1 + 1312)); 272 | *(_DWORD *)(a1 + 1312) = Curl_cstrdup(a2); 273 | if ( *(_DWORD *)(a1 + 1312) ) 274 | { 275 | v6[5] = 0; 276 | *v6 = Curl_thread_create((int)getaddrinfo_thread, (int)(v6 + 4)); 277 | if ( *v6 ) 278 | return 1; 279 | v6[5] = (pthread_t *)(&__cxa_finalize + 1); 280 | v5 = *_errno_location(); 281 | } 282 | destroy_async_data((_DWORD *)(a1 + 1312)); 283 | } 284 | else 285 | { 286 | *(_DWORD *)(a1 + 1328) = 0; 287 | Curl_cfree(v6); 288 | } 289 | } 290 | *_errno_location() = v5; 291 | return 0; 292 | } 293 | ///// 294 | __fastcall resolver_error(int *a1) 295 | { 296 | int v2; 297 | if ( a1[305] >= 0 ) 298 | { 299 | v2 = 6; 300 | Curl_failf(*a1, "Could not resolve %s: %s", (int)"host", a1[328]); 301 | } 302 | else 303 | { 304 | v2 = 5; 305 | Curl_failf(*a1, "Could not resolve %s: %s", (int)"proxy", a1[328]); 306 | } 307 | return v2; 308 | } 309 | ///// 310 | __fastcall thread_wait_resolv(int a1, _DWORD *a2, char a3) 311 | { 312 | int v4; 313 | v4 = 0; 314 | if ( Curl_thread_join(*(pthread_t ***)(a1 + 1328)) && a2 ) 315 | v4 = getaddrinfo_complete(a1); 316 | *(_BYTE *)(a1 + 1332) = *(_BYTE *)(a1 + 1332) & 0x7F | 0x80; 317 | if ( a2 ) 318 | *a2 = *(_DWORD *)(a1 + 1320); 319 | if ( !*(_DWORD *)(a1 + 1320) && a3 ) 320 | v4 = resolver_error((int *)a1); 321 | destroy_async_data((_DWORD *)(a1 + 1312)); 322 | if ( !*(_DWORD *)(a1 + 1320) && a3 ) 323 | Curl_conncontrol(a1, 1); 324 | return v4; 325 | } 326 | ///// 327 | __fastcall Curl_resolver_kill(int a1) 328 | { 329 | _DWORD *result; 330 | _DWORD *v2; 331 | v2 = *(_DWORD **)(a1 + 1328); 332 | if ( v2 && *v2 ) 333 | result = (_DWORD *)thread_wait_resolv(a1, 0, 0); 334 | else 335 | result = Curl_resolver_cancel(a1); 336 | return result; 337 | } 338 | ///// 339 | __fastcall decodeQuantum(_BYTE *a1, _BYTE *a2) 340 | { 341 | unsigned int v3; 342 | const char *j; 343 | unsigned int i; 344 | unsigned int v7; 345 | unsigned int v8; 346 | int v9; 347 | v3 = 0; 348 | v7 = 0; 349 | for ( i = 0; i < 4; ++i ) 350 | { 351 | if ( *a2 == 61 ) 352 | { 353 | v7 <<= 6; 354 | ++v3; 355 | } 356 | else 357 | { 358 | v9 = 0; 359 | for ( j = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; *j && *j != (char)*a2; ++j ) 360 | ++v9; 361 | if ( *j != (char)*a2 ) 362 | return 0; 363 | v7 = v9 + (v7 << 6); 364 | } 365 | ++a2; 366 | } 367 | if ( !v3 ) 368 | a1[2] = curlx_ultouc(v7); 369 | v8 = v7 >> 8; 370 | if ( v3 < 2 ) 371 | a1[1] = curlx_ultouc(v8); 372 | *a1 = curlx_ultouc(BYTE2(v8)); 373 | return 3 - v3; 374 | } 375 | ///// 376 | __fastcall base64_encode(int a1, int a2, const char *a3, size_t a4, char **a5, size_t *a6) 377 | { 378 | int i; 379 | int v9; 380 | char *v10; 381 | char *s; 382 | char *v12; 383 | unsigned __int8 v13; 384 | unsigned __int8 v14; 385 | unsigned __int8 v15; 386 | unsigned __int8 v16; 387 | unsigned __int8 v17; 388 | unsigned __int8 v18; 389 | unsigned __int8 v19; 390 | size_t v20; 391 | v20 = a4; 392 | s = (char *)a3; 393 | *a5 = 0; 394 | *a6 = 0; 395 | if ( !a4 ) 396 | v20 = strlen(a3); 397 | if ( v20 >= 0x40000000 ) 398 | return 27; 399 | v10 = (char *)Curl_cmalloc(4 * v20 / 3 + 4); 400 | v12 = v10; 401 | if ( !v10 ) 402 | return 27; 403 | while ( v20 ) 404 | { 405 | v9 = 0; 406 | for ( i = 0; i < 3; ++i ) 407 | { 408 | if ( v20 ) 409 | { 410 | ++v9; 411 | *(&v13 + i) = *s++; 412 | --v20; 413 | } 414 | else 415 | { 416 | *(&v13 + i) = 0; 417 | } 418 | } 419 | v16 = v13 >> 2; 420 | v17 = (16 * v13) & 0x30 | (v14 >> 4); 421 | v18 = (4 * v14) & 0x3C | (v15 >> 6); 422 | v19 = v15 & 0x3F; 423 | if ( v9 == 1 ) 424 | { 425 | curl_msnprintf((int)v10, 5, (int)"%c%c==", *(char *)(a1 + v16), *(char *)(a1 + v17)); 426 | } 427 | else if ( v9 == 2 ) 428 | { 429 | curl_msnprintf((int)v10, 5, (int)"%c%c%c=", *(char *)(a1 + v16), *(char *)(a1 + v17), *(char *)(a1 + v18)); 430 | } 431 | else 432 | { 433 | curl_msnprintf( 434 | (int)v10, 435 | 5, 436 | (int)"%c%c%c%c", 437 | *(char *)(a1 + v16), 438 | *(char *)(a1 + v17), 439 | *(char *)(a1 + v18), 440 | *(char *)(a1 + v19)); 441 | } 442 | v10 += 4; 443 | } 444 | *v10 = 0; 445 | *a5 = v12; 446 | Curl_cfree(0); 447 | *a6 = strlen(v12); 448 | return 0; 449 | } 450 | ///// 451 | __fastcall conn_llist_dtor(int a1, int a2) 452 | { 453 | int result; 454 | result = a2; 455 | *(_DWORD *)(a2 + 1528) = 0; 456 | return result; 457 | } 458 | ///// 459 | __fastcall bundle_create(int a1) 460 | { 461 | *(_DWORD *)a1 = Curl_cmalloc(24); 462 | if ( !*(_DWORD *)a1 ) 463 | return 27; 464 | *(_DWORD *)(*(_DWORD *)a1 + 4) = 0; 465 | **(_DWORD **)a1 = 0; 466 | Curl_llist_init((_DWORD *)(*(_DWORD *)a1 + 8), (int)conn_llist_dtor); 467 | return 0; 468 | } 469 | ///// 470 | __fastcall bundle_destroy(int a1) 471 | { 472 | int result; 473 | result = a1; 474 | if ( a1 ) 475 | { 476 | Curl_llist_destroy(a1 + 8, 0); 477 | result = Curl_cfree(a1); 478 | } 479 | return result; 480 | } 481 | ///// 482 | __fastcall bundle_add_conn(_DWORD *a1, int a2) 483 | { 484 | _DWORD *result; 485 | Curl_llist_insert_next(a1 + 2, a1[3], a2, (_DWORD *)(a2 + 616)); 486 | *(_DWORD *)(a2 + 1528) = a1; 487 | result = a1; 488 | ++a1[1]; 489 | return result; 490 | } 491 | ///// 492 | __fastcall bundle_remove_conn(int a1, int a2) 493 | { 494 | int *i; 495 | for ( i = *(int **)(a1 + 8); i; i = (int *)i[2] ) 496 | { 497 | if ( a2 == *i ) 498 | { 499 | Curl_llist_remove((int **)(a1 + 8), i, 0); 500 | --*(_DWORD *)(a1 + 4); 501 | *(_DWORD *)(a2 + 1528) = 0; 502 | return 1; 503 | } 504 | } 505 | return 0; 506 | } 507 | ///// 508 | __fastcall Curl_conncache_init(_DWORD *a1, int a2) 509 | { 510 | int v3; 511 | a1[10] = curl_easy_init(); 512 | if ( !a1[10] ) 513 | return 1; 514 | v3 = Curl_hash_init(a1, a2, (int)Curl_hash_str, (int)Curl_str_key_compare, (int)free_bundle_hash_entry); 515 | if ( v3 ) 516 | Curl_close(a1 + 10); 517 | else 518 | *(_DWORD *)(a1[10] + 3136) = a1; 519 | return v3; 520 | } 521 | ///// 522 | __fastcall Curl_conncache_destroy(_DWORD *a1) 523 | { 524 | _DWORD *result; 525 | result = a1; 526 | if ( a1 ) 527 | result = Curl_hash_destroy(a1); 528 | return result; 529 | } 530 | ///// 531 | __fastcall hashkey(_DWORD *a1, int a2, int a3, const char **a4) 532 | { 533 | const char *v5; 534 | int v6; 535 | v6 = a1[218]; 536 | if ( (int)a1[305] >= 0 || (a1[305] & 0x10000000) != 0 ) 537 | { 538 | if ( (a1[305] & 0x800000) != 0 ) 539 | v5 = (const char *)a1[199]; 540 | else 541 | v5 = (const char *)a1[193]; 542 | } 543 | else 544 | { 545 | v5 = (const char *)a1[211]; 546 | v6 = a1[217]; 547 | } 548 | if ( a4 ) 549 | *a4 = v5; 550 | return curl_msnprintf(a2, a3, (int)"%ld%s", v6, v5); 551 | } 552 | ///// 553 | __fastcall Curl_conncache_find_bundle(int *a1, int *a2, const char **a3) 554 | { 555 | int v3; 556 | int v8; 557 | char v9[128]; 558 | v8 = 0; 559 | if ( *(_DWORD *)(*a1 + 128) ) 560 | Curl_share_lock(*a1, 5, 2); 561 | if ( a2 ) 562 | { 563 | hashkey(a1, (int)v9, 128, a3); 564 | v3 = strlen(v9); 565 | v8 = Curl_hash_pick(a2, (int)v9, v3); 566 | } 567 | return v8; 568 | } 569 | ///// 570 | __fastcall conncache_add_bundle(int a1, const char *a2, int a3) 571 | { 572 | size_t v4; 573 | v4 = strlen(a2); 574 | return Curl_hash_add(a1, a2, v4, a3) != 0; 575 | } 576 | ///// 577 | __fastcall conncache_remove_bundle(int a1, int a2) 578 | { 579 | int i; 580 | _DWORD v6[3]; 581 | if ( a1 ) 582 | { 583 | Curl_hash_start_iterate(a1, v6); 584 | for ( i = Curl_hash_next_element((int)v6); i; i = Curl_hash_next_element((int)v6) ) 585 | { 586 | if ( a2 == *(_DWORD *)(i + 12) ) 587 | { 588 | Curl_hash_delete(a1, i + 20, *(_DWORD *)(i + 16)); 589 | return _stack_chk_guard; 590 | } 591 | } 592 | } 593 | return _stack_chk_guard; 594 | } 595 | ///// 596 | __fastcall Curl_conncache_remove_conn(int a1, int a2, unsigned __int8 a3) 597 | { 598 | int result; 599 | int v4; 600 | int v5; 601 | v4 = *(_DWORD *)(a2 + 1528); 602 | v5 = *(_DWORD *)(a1 + 3136); 603 | result = v4; 604 | if ( v4 ) 605 | { 606 | if ( a3 && *(_DWORD *)(a1 + 128) ) 607 | Curl_share_lock(a1, 5, 2); 608 | bundle_remove_conn(v4, a2); 609 | if ( !*(_DWORD *)(v4 + 4) ) 610 | conncache_remove_bundle(v5, v4); 611 | *(_DWORD *)(a2 + 1528) = 0; 612 | if ( v5 ) 613 | --*(_DWORD *)(v5 + 24); 614 | result = a3; 615 | if ( a3 ) 616 | { 617 | result = *(_DWORD *)(a1 + 128); 618 | if ( result ) 619 | result = Curl_share_unlock(a1, 5); 620 | } 621 | } 622 | return result; 623 | } 624 | ///// 625 | __fastcall conncache_find_first_connection(int a1) 626 | { 627 | int i; 628 | int v3; 629 | _DWORD v4[3]; 630 | Curl_hash_start_iterate(a1, v4); 631 | for ( i = Curl_hash_next_element((int)v4); i; i = Curl_hash_next_element((int)v4) ) 632 | { 633 | v3 = *(_DWORD *)(*(_DWORD *)(i + 12) + 8); 634 | if ( v3 ) 635 | return *(_DWORD *)v3; 636 | } 637 | return 0; 638 | } 639 | ///// 640 | __fastcall Curl_conncache_extract_bundle(int a1, int a2) 641 | { 642 | __int64 v2; 643 | _DWORD *i; 644 | _DWORD *v7; 645 | _DWORD *v8; 646 | __int64 v9; 647 | __time_t v10[2]; 648 | LODWORD(v9) = -1; 649 | HIDWORD(v9) = -1; 650 | v7 = 0; 651 | Curl_now(v10); 652 | for ( i = *(_DWORD **)(a2 + 8); i; i = (_DWORD *)i[2] ) 653 | { 654 | v8 = (_DWORD *)*i; 655 | if ( !*(_DWORD *)(*i + 1300) && !*v8 ) 656 | { 657 | v2 = Curl_timediff(v10[0], v10[1], v8[256], v8[257]); 658 | if ( v9 < v2 ) 659 | { 660 | v9 = v2; 661 | v7 = v8; 662 | } 663 | } 664 | } 665 | if ( v7 ) 666 | { 667 | bundle_remove_conn(a2, (int)v7); 668 | --*(_DWORD *)(*(_DWORD *)(a1 + 3136) + 24); 669 | *v7 = a1; 670 | } 671 | return v7; 672 | } 673 | ///// 674 | __fastcall Curl_conncache_extract_oldest(int a1) 675 | { 676 | __int64 v1; 677 | int **j; 678 | int i; 679 | int *v6; 680 | int v7; 681 | int v8; 682 | int v9; 683 | int *v10; 684 | __int64 v11; 685 | __time_t v12[2]; 686 | _DWORD v13[3]; 687 | v8 = *(_DWORD *)(a1 + 3136); 688 | LODWORD(v11) = -1; 689 | HIDWORD(v11) = -1; 690 | v6 = 0; 691 | v7 = 0; 692 | Curl_now(v12); 693 | if ( *(_DWORD *)(a1 + 128) ) 694 | Curl_share_lock(a1, 5, 2); 695 | Curl_hash_start_iterate(v8, v13); 696 | for ( i = Curl_hash_next_element((int)v13); i; i = Curl_hash_next_element((int)v13) ) 697 | { 698 | v9 = *(_DWORD *)(i + 12); 699 | for ( j = *(int ***)(v9 + 8); j; j = (int **)j[2] ) 700 | { 701 | v10 = *j; 702 | if ( !(*j)[325] && !*v10 && (v10[305] & 0x4000000) == 0 && (v10[305] & 8) == 0 ) 703 | { 704 | v1 = Curl_timediff(v12[0], v12[1], v10[256], v10[257]); 705 | if ( v11 < v1 ) 706 | { 707 | v11 = v1; 708 | v6 = v10; 709 | v7 = v9; 710 | } 711 | } 712 | } 713 | } 714 | if ( v6 ) 715 | { 716 | bundle_remove_conn(v7, (int)v6); 717 | --*(_DWORD *)(v8 + 24); 718 | *v6 = a1; 719 | } 720 | if ( *(_DWORD *)(a1 + 128) ) 721 | Curl_share_unlock(a1, 5); 722 | return v6; 723 | } 724 | ///// 725 | __fastcall Curl_conncache_close_all_connections(int a1) 726 | { 727 | int v1; 728 | int *i; 729 | char v5; 730 | if ( *(_DWORD *)(a1 + 40) ) 731 | { 732 | *(_DWORD *)(*(_DWORD *)(a1 + 40) + 3168) = &v5; 733 | *(_DWORD *)(*(_DWORD *)(a1 + 40) + 2288) = 1024; 734 | for ( i = (int *)conncache_find_first_connection(a1); i; i = (int *)conncache_find_first_connection(a1) ) 735 | { 736 | *i = *(_DWORD *)(a1 + 40); 737 | Curl_conncontrol((int)i, 1); 738 | Curl_conncache_remove_conn(*i, (int)i, 1u); 739 | Curl_disconnect(*(_DWORD *)(a1 + 40), (int)i, 0, v1); 740 | } 741 | *(_DWORD *)(*(_DWORD *)(a1 + 40) + 3168) = 0; 742 | if ( *(_DWORD *)(a1 + 40) ) 743 | { 744 | Curl_hostcache_clean(*(_DWORD *)(a1 + 40), *(_DWORD **)(*(_DWORD *)(a1 + 40) + 112)); 745 | Curl_close(a1 + 40); 746 | } 747 | } 748 | return _stack_chk_guard; 749 | } 750 | ///// 751 | __fastcall verifyconnect(int a1, _DWORD *a2) 752 | { 753 | bool v4; 754 | int v5; 755 | socklen_t optlen; 756 | v5 = 0; 757 | optlen = 4; 758 | if ( getsockopt(a1, 0xFFFF, 4103, &v5, &optlen) ) 759 | v5 = *_errno_location(); 760 | v4 = !v5 || v5 == 133; 761 | if ( a2 ) 762 | *a2 = v5; 763 | return v4; 764 | } 765 | ///// 766 | __fastcall trynextip(int *a1, int a2, int a3) 767 | { 768 | int v4; 769 | int i; 770 | int v6; 771 | v4 = 7; 772 | v6 = a1[a3 + 260]; 773 | a1[a3 + 260] = -1; 774 | if ( !a2 ) 775 | { 776 | for ( i = a1[a3 + 175]; i; i = ainext((int)a1, a3, 1) ) 777 | { 778 | v4 = singleipconnect(a1, i, a3); 779 | if ( v4 != 7 ) 780 | break; 781 | } 782 | } 783 | if ( v6 != -1 ) 784 | Curl_closesocket((int)a1, v6); 785 | return v4; 786 | } 787 | ///// 788 | __fastcall Curl_persistconninfo(int *a1) 789 | { 790 | int result; 791 | memcpy((void *)(*a1 + 4040), (char *)a1 + 882, 0x2Eu); 792 | memcpy((void *)(*a1 + 4092), a1 + 233, 0x2Eu); 793 | *(_DWORD *)(*a1 + 4144) = *(_DWORD *)a1[314]; 794 | *(_DWORD *)(*a1 + 4148) = *(_DWORD *)(a1[314] + 64); 795 | *(_DWORD *)(*a1 + 4088) = a1[232]; 796 | result = *a1; 797 | *(_DWORD *)(*a1 + 4140) = a1[245]; 798 | return result; 799 | } 800 | ///// 801 | __fastcall Curl_updateconninfo(int a1, int a2) 802 | { 803 | char *v2; 804 | char *v3; 805 | int v4; 806 | int *v5; 807 | char *v6; 808 | int v7; 809 | int *v8; 810 | char *v9; 811 | socklen_t v12; 812 | socklen_t v13; 813 | int v14; 814 | int v15; 815 | int v16; 816 | struct sockaddr v17[8]; 817 | struct sockaddr v18[8]; 818 | char v19[256]; 819 | if ( *(_DWORD *)(a1 + 760) != 3 || (*(_DWORD *)(a1 + 1220) & 0x2000000) != 0 || (*(_DWORD *)(a1 + 1220) & 0x40) != 0 ) 820 | goto LABEL_12; 821 | v14 = *(_DWORD *)a1; 822 | v12 = 128; 823 | if ( !getpeername(a2, v17, &v12) ) 824 | { 825 | v13 = 128; 826 | memset(v18, 0, sizeof(v18)); 827 | if ( getsockname(a2, v18, &v13) ) 828 | { 829 | v15 = *_errno_location(); 830 | v3 = Curl_strerror(v15, v19, 256); 831 | Curl_failf(v14, "getsockname() failed with errno %d: %s", v15, (int)v3); 832 | return _stack_chk_guard; 833 | } 834 | if ( (unsigned __int8)Curl_addr2string((uint16_t *)v17, v12, (char *)(a1 + 882), (_DWORD *)(a1 + 928)) != 1 ) 835 | { 836 | v4 = *_errno_location(); 837 | v5 = _errno_location(); 838 | v6 = Curl_strerror(*v5, v19, 256); 839 | Curl_failf(v14, "ssrem inet_ntop() failed with errno %d: %s", v4, (int)v6); 840 | return _stack_chk_guard; 841 | } 842 | memcpy((void *)(a1 + 708), (const void *)(a1 + 882), 0x2Eu); 843 | if ( (unsigned __int8)Curl_addr2string((uint16_t *)v18, v13, (char *)(a1 + 932), (_DWORD *)(a1 + 980)) != 1 ) 844 | { 845 | v7 = *_errno_location(); 846 | v8 = _errno_location(); 847 | v9 = Curl_strerror(*v8, v19, 256); 848 | Curl_failf(v14, "ssloc inet_ntop() failed with errno %d: %s", v7, (int)v9); 849 | return _stack_chk_guard; 850 | } 851 | LABEL_12: 852 | Curl_persistconninfo((int *)a1); 853 | return _stack_chk_guard; 854 | } 855 | v16 = *_errno_location(); 856 | v2 = Curl_strerror(v16, v19, 256); 857 | Curl_failf(v14, "getpeername() failed with errno %d: %s", v16, (int)v2); 858 | return _stack_chk_guard; 859 | } 860 | ///// 861 | __fastcall connect_SOCKS(int a1, int a2, _BYTE *a3, int a4) 862 | { 863 | const char *v4; 864 | int v5; 865 | unsigned int v6; 866 | int v8; 867 | const char *v9; 868 | int v10; 869 | v8 = 0; 870 | if ( (*(_DWORD *)(a1 + 1220) & 0x40000000) == 0 ) 871 | { 872 | *a3 = 1; 873 | return v8; 874 | } 875 | if ( *(int *)(a1 + 1220) >= 0 ) 876 | { 877 | if ( (*(_DWORD *)(a1 + 1220) & 0x800000) != 0 ) 878 | { 879 | v4 = *(const char **)(a1 + 796); 880 | } 881 | else if ( a2 == 1 ) 882 | { 883 | v4 = *(const char **)(a1 + 784); 884 | } 885 | else 886 | { 887 | v4 = *(const char **)(a1 + 772); 888 | } 889 | } 890 | else 891 | { 892 | v4 = *(const char **)(a1 + 844); 893 | } 894 | v9 = v4; 895 | if ( *(int *)(a1 + 1220) >= 0 ) 896 | { 897 | if ( a2 == 1 ) 898 | { 899 | v5 = *(unsigned __int16 *)(a1 + 880); 900 | } 901 | else if ( (*(_DWORD *)(a1 + 1220) & 0x400000) != 0 ) 902 | { 903 | v5 = *(_DWORD *)(a1 + 876); 904 | } 905 | else 906 | { 907 | v5 = *(_DWORD *)(a1 + 872); 908 | } 909 | } 910 | else 911 | { 912 | v5 = *(_DWORD *)(a1 + 852); 913 | } 914 | v10 = v5; 915 | v6 = *(_DWORD *)(a1 + 824); 916 | if ( v6 != 5 ) 917 | { 918 | if ( v6 < 6 ) 919 | { 920 | if ( v6 != 4 ) 921 | goto LABEL_24; 922 | return Curl_SOCKS4(*(const char **)(a1 + 828), v9, v10, a2, a1, a3); 923 | } 924 | if ( v6 == 6 ) 925 | return Curl_SOCKS4(*(const char **)(a1 + 828), v9, v10, a2, a1, a3); 926 | if ( v6 != 7 ) 927 | { 928 | LABEL_24: 929 | Curl_failf(*(_DWORD *)a1, "unknown proxytype option given", (int)a3, a4); 930 | return 7; 931 | } 932 | } 933 | return Curl_SOCKS5(*(const char **)(a1 + 828), *(const char **)(a1 + 832), v9, v10, a2, a1, a3); 934 | } 935 | ///// 936 | __fastcall post_SOCKS(int *a1, int a2, _BYTE *a3) 937 | { 938 | int result; 939 | *((_BYTE *)a1 + a2 + 1216) = 1; 940 | *a3 = 1; 941 | if ( !a2 ) 942 | Curl_pgrsTime(*a1, 4); 943 | Curl_updateconninfo((int)a1, a1[a2 + 258]); 944 | Curl_verboseconnect(a1); 945 | result = *a1; 946 | ++*(_DWORD *)(*a1 + 4016); 947 | return result; 948 | } 949 | ///// 950 | __fastcall tcpnodelay(int *a1, int a2) 951 | { 952 | int *v2; 953 | char *v3; 954 | int v4; 955 | int v6[2]; 956 | int v7; 957 | char v8[256]; 958 | v6[0] = 1; 959 | v6[1] = 6; 960 | v7 = *a1; 961 | if ( setsockopt(a2, 6, 1, v6, 4u) < 0 ) 962 | { 963 | v2 = _errno_location(); 964 | v3 = Curl_strerror(*v2, v8, 256); 965 | Curl_infof(v7, "Could not set TCP_NODELAY: %s\n", (int)v3, v4); 966 | } 967 | return _stack_chk_guard; 968 | } 969 | ///// 970 | __fastcall conn_is_conn(int a1, int a2) 971 | { 972 | if ( a1 != *(_DWORD *)a2 ) 973 | return 0; 974 | *(_BYTE *)(a2 + 4) = 1; 975 | return 1; 976 | } 977 | ///// 978 | __fastcall Curl_closesocket(int a1, int a2) 979 | { 980 | int v3; 981 | if ( a1 && *(_DWORD *)(a1 + 680) ) 982 | { 983 | if ( a2 != *(_DWORD *)(a1 + 1036) || *(int *)(a1 + 1224) >= 0 ) 984 | { 985 | Curl_multi_closed(*(_DWORD *)a1, a2); 986 | Curl_set_in_callback(*(_DWORD *)a1, 1); 987 | v3 = (*(int (__fastcall **)(_DWORD, int))(a1 + 680))(*(_DWORD *)(a1 + 684), a2); 988 | Curl_set_in_callback(*(_DWORD *)a1, 0); 989 | return v3; 990 | } 991 | *(_DWORD *)(a1 + 1224) &= 0x7FFFFFFFu; 992 | } 993 | if ( a1 ) 994 | Curl_multi_closed(*(_DWORD *)a1, a2); 995 | close(a2); 996 | return 0; 997 | } 998 | ///// 999 | __fastcall Curl_conncontrol(int a1, int a2) 1000 | { 1001 | bool v2; 1002 | unsigned int result; 1003 | bool v4; 1004 | v2 = a2 == 1 || a2 == 2 && (*(_DWORD *)(*(_DWORD *)(a1 + 1256) + 68) & 0x200) == 0; 1005 | v4 = v2; 1006 | if ( a2 != 2 || (result = *(_DWORD *)(*(_DWORD *)(a1 + 1256) + 68) & 0x200) == 0 ) 1007 | { 1008 | result = (*(_DWORD *)(a1 + 1220) & 0x4000000) != 0; 1009 | if ( v4 != result ) 1010 | { 1011 | result = *(_DWORD *)(a1 + 1220) & 0xFBFFFFFF | (v4 << 26); 1012 | *(_DWORD *)(a1 + 1220) = result; 1013 | } 1014 | } 1015 | return result; 1016 | } 1017 | ///// 1018 | __fastcall cookie_list(int a1) 1019 | { 1020 | _DWORD *v2; 1021 | _DWORD *j; 1022 | unsigned int i; 1023 | int v5; 1024 | _DWORD *v6; 1025 | v2 = 0; 1026 | if ( !*(_DWORD *)(a1 + 2836) || !*(_DWORD *)(*(_DWORD *)(a1 + 2836) + 1032) ) 1027 | return 0; 1028 | for ( i = 0; i < 0x100; ++i ) 1029 | { 1030 | for ( j = *(_DWORD **)(*(_DWORD *)(a1 + 2836) + 4 * i); j; j = (_DWORD *)*j ) 1031 | { 1032 | if ( j[5] ) 1033 | { 1034 | v5 = get_netscape_format((int)j); 1035 | if ( !v5 ) 1036 | { 1037 | curl_slist_free_all(v2); 1038 | return 0; 1039 | } 1040 | v6 = Curl_slist_append_nodup((int)v2, v5); 1041 | if ( !v6 ) 1042 | { 1043 | Curl_cfree(v5); 1044 | curl_slist_free_all(v2); 1045 | return 0; 1046 | } 1047 | v2 = v6; 1048 | } 1049 | } 1050 | } 1051 | return v2; 1052 | } 1053 | ///// 1054 | __fastcall Curl_cookie_list(int a1) 1055 | { 1056 | _DWORD *v2; 1057 | Curl_share_lock(a1, 2, 2); 1058 | v2 = cookie_list(a1); 1059 | Curl_share_unlock(a1, 2); 1060 | return v2; 1061 | } 1062 | ///// 1063 | __fastcall Curl_flush_cookies(_DWORD *a1, char a2) 1064 | { 1065 | int v2; 1066 | if ( a1[596] ) 1067 | { 1068 | if ( a1[706] ) 1069 | Curl_cookie_loadfiles(a1); 1070 | Curl_share_lock((int)a1, 2, 2); 1071 | if ( cookie_output((int)a1, a1[709], (const char *)a1[596]) ) 1072 | Curl_infof((int)a1, "WARNING: failed to save cookies in %s\n", a1[596], v2); 1073 | } 1074 | else 1075 | { 1076 | if ( a2 && a1[706] ) 1077 | { 1078 | curl_slist_free_all((_DWORD *)a1[706]); 1079 | a1[706] = 0; 1080 | } 1081 | Curl_share_lock((int)a1, 2, 2); 1082 | } 1083 | if ( a2 && (!a1[32] || a1[709] != *(_DWORD *)(a1[32] + 88)) ) 1084 | { 1085 | Curl_cookie_cleanup(a1[709]); 1086 | a1[709] = 0; 1087 | } 1088 | return Curl_share_unlock((int)a1, 2); 1089 | } 1090 | ///// 1091 | __fastcall Curl_freeaddrinfo(int a1) 1092 | { 1093 | int result; 1094 | int v3; 1095 | while ( 1 ) 1096 | { 1097 | result = a1; 1098 | if ( !a1 ) 1099 | break; 1100 | v3 = *(_DWORD *)(a1 + 28); 1101 | Curl_cfree(a1); 1102 | a1 = v3; 1103 | } 1104 | return result; 1105 | } 1106 | ///// 1107 | __fastcall Curl_getaddrinfo_ex(const char *a1, const char *a2, const struct addrinfo *a3, _DWORD *a4) 1108 | { 1109 | size_t v5; 1110 | struct addrinfo *v7; 1111 | struct addrinfo *i; 1112 | int v9; 1113 | int v10; 1114 | size_t n; 1115 | int v12; 1116 | size_t v13; 1117 | int v14; 1118 | v9 = 0; 1119 | v10 = 0; 1120 | *a4 = 0; 1121 | v12 = getaddrinfo(a1, a2, a3, &v7); 1122 | if ( v12 ) 1123 | return v12; 1124 | for ( i = v7; i; i = i->ai_next ) 1125 | { 1126 | if ( i->ai_canonname ) 1127 | v5 = strlen(i->ai_canonname) + 1; 1128 | else 1129 | v5 = 0; 1130 | v13 = v5; 1131 | if ( i->ai_family == 2 ) 1132 | { 1133 | n = 16; 1134 | } 1135 | else 1136 | { 1137 | if ( i->ai_family != 10 ) 1138 | continue; 1139 | n = 28; 1140 | } 1141 | if ( i->ai_addr && i->ai_addrlen && i->ai_addrlen >= n ) 1142 | { 1143 | v14 = Curl_cmalloc(n + v13 + 32); 1144 | if ( !v14 ) 1145 | { 1146 | v12 = -10; 1147 | break; 1148 | } 1149 | *(_DWORD *)v14 = i->ai_flags; 1150 | *(_DWORD *)(v14 + 4) = i->ai_family; 1151 | *(_DWORD *)(v14 + 8) = i->ai_socktype; 1152 | *(_DWORD *)(v14 + 12) = i->ai_protocol; 1153 | *(_DWORD *)(v14 + 16) = n; 1154 | *(_DWORD *)(v14 + 24) = 0; 1155 | *(_DWORD *)(v14 + 20) = 0; 1156 | *(_DWORD *)(v14 + 28) = 0; 1157 | *(_DWORD *)(v14 + 24) = v14 + 32; 1158 | memcpy(*(void **)(v14 + 24), i->ai_addr, n); 1159 | if ( v13 ) 1160 | { 1161 | *(_DWORD *)(v14 + 20) = *(_DWORD *)(v14 + 24) + n; 1162 | memcpy(*(void **)(v14 + 20), i->ai_canonname, v13); 1163 | } 1164 | if ( !v9 ) 1165 | v9 = v14; 1166 | if ( v10 ) 1167 | *(_DWORD *)(v10 + 28) = v14; 1168 | v10 = v14; 1169 | } 1170 | } 1171 | if ( v7 ) 1172 | freeaddrinfo(v7); 1173 | if ( v12 ) 1174 | { 1175 | Curl_freeaddrinfo(v9); 1176 | v9 = 0; 1177 | } 1178 | else if ( !v9 ) 1179 | { 1180 | v12 = -2; 1181 | } 1182 | *a4 = v9; 1183 | return v12; 1184 | } 1185 | ///// 1186 | __fastcall Curl_he2ai(int a1, uint16_t a2) 1187 | { 1188 | int v3; 1189 | int v4; 1190 | int v5; 1191 | int v6; 1192 | int i; 1193 | int v8; 1194 | void *src; 1195 | size_t n; 1196 | int v11; 1197 | _WORD *v12; 1198 | _WORD *v13; 1199 | v4 = 0; 1200 | v5 = 0; 1201 | v6 = 0; 1202 | if ( !a1 ) 1203 | return 0; 1204 | for ( i = 0; ; ++i ) 1205 | { 1206 | src = *(void **)(*(_DWORD *)(a1 + 16) + 4 * i); 1207 | if ( !src ) 1208 | break; 1209 | n = strlen(*(const char **)a1) + 1; 1210 | if ( *(_DWORD *)(a1 + 8) == 10 ) 1211 | v8 = 28; 1212 | else 1213 | v8 = 16; 1214 | v11 = Curl_ccalloc(1, v8 + n + 32); 1215 | if ( !v11 ) 1216 | { 1217 | v6 = 27; 1218 | break; 1219 | } 1220 | *(_DWORD *)(v11 + 24) = v11 + 32; 1221 | *(_DWORD *)(v11 + 20) = *(_DWORD *)(v11 + 24) + v8; 1222 | memcpy(*(void **)(v11 + 20), *(const void **)a1, n); 1223 | if ( !v5 ) 1224 | v5 = v11; 1225 | if ( v4 ) 1226 | *(_DWORD *)(v4 + 28) = v11; 1227 | *(_DWORD *)(v11 + 4) = *(_DWORD *)(a1 + 8); 1228 | *(_DWORD *)(v11 + 8) = 2; 1229 | *(_DWORD *)(v11 + 16) = v8; 1230 | v3 = *(_DWORD *)(v11 + 4); 1231 | if ( v3 == 2 ) 1232 | { 1233 | v13 = *(_WORD **)(v11 + 24); 1234 | memcpy(v13 + 2, src, 4u); 1235 | *v13 = *(_DWORD *)(a1 + 8); 1236 | v13[1] = htons(a2); 1237 | } 1238 | else if ( v3 == 10 ) 1239 | { 1240 | v12 = *(_WORD **)(v11 + 24); 1241 | memcpy(v12 + 4, src, 0x10u); 1242 | *v12 = *(_DWORD *)(a1 + 8); 1243 | v12[1] = htons(a2); 1244 | } 1245 | v4 = v11; 1246 | } 1247 | if ( v6 ) 1248 | { 1249 | Curl_freeaddrinfo(v5); 1250 | v5 = 0; 1251 | } 1252 | return v5; 1253 | } 1254 | ///// 1255 | __fastcall Curl_ip2addr(int a1, const void *a2, int a3, uint16_t a4) 1256 | { 1257 | void *dest; 1258 | __int16 v6; 1259 | int v7; 1260 | int v8; 1261 | int v9; 1262 | v7 = Curl_cmalloc(44); 1263 | if ( !v7 ) 1264 | return 0; 1265 | v8 = Curl_cstrdup(a3); 1266 | if ( !v8 ) 1267 | { 1268 | Curl_cfree(v7); 1269 | return 0; 1270 | } 1271 | if ( a1 == 2 ) 1272 | { 1273 | v6 = 4; 1274 | dest = (void *)(v7 + 20); 1275 | memcpy((void *)(v7 + 20), a2, 4u); 1276 | } 1277 | else 1278 | { 1279 | if ( a1 != 10 ) 1280 | { 1281 | Curl_cfree(v8); 1282 | Curl_cfree(v7); 1283 | return 0; 1284 | } 1285 | v6 = 16; 1286 | dest = (void *)(v7 + 20); 1287 | memcpy((void *)(v7 + 20), a2, 0x10u); 1288 | } 1289 | *(_DWORD *)v7 = v8; 1290 | *(_QWORD *)(v7 + 4) = (unsigned int)(__int16)a1; 1291 | *(_DWORD *)(v7 + 12) = v6; 1292 | *(_DWORD *)(v7 + 16) = v7 + 36; 1293 | **(_DWORD **)(v7 + 16) = dest; 1294 | *(_DWORD *)(*(_DWORD *)(v7 + 16) + 4) = 0; 1295 | v9 = Curl_he2ai(v7, a4); 1296 | Curl_cfree(v8); 1297 | Curl_cfree(v7); 1298 | return v9; 1299 | } 1300 | ///// 1301 | __fastcall Curl_unix2addr(const char *a1, _BYTE *a2, char a3) 1302 | { 1303 | _DWORD *result; 1304 | _DWORD *v4; 1305 | _WORD *v5; 1306 | size_t n; 1307 | *a2 = 0; 1308 | v4 = (_DWORD *)Curl_ccalloc(1, 142); 1309 | if ( !v4 ) 1310 | return 0; 1311 | v4[6] = v4 + 8; 1312 | v5 = (_WORD *)v4[6]; 1313 | *v5 = 1; 1314 | n = strlen(a1) + 1; 1315 | if ( n < 0x6D ) 1316 | { 1317 | v4[1] = 1; 1318 | v4[2] = 2; 1319 | v4[4] = (n + 2) & 0x7FFFFFFF; 1320 | if ( a3 ) 1321 | memcpy((char *)v5 + 3, a1, n - 1); 1322 | else 1323 | memcpy(v5 + 1, a1, n); 1324 | result = v4; 1325 | } 1326 | else 1327 | { 1328 | Curl_cfree(v4); 1329 | *a2 = 1; 1330 | result = 0; 1331 | } 1332 | return result; 1333 | } 1334 | ///// 1335 | __fastcall Curl_isdigit(int a1) 1336 | { 1337 | int result; 1338 | if ( a1 >= 0 && a1 < 128 ) 1339 | result = ascii[a1] & 4; 1340 | else 1341 | result = 0; 1342 | return result; 1343 | } 1344 | ///// 1345 | __fastcall unescape_word(int a1, const char *a2) 1346 | { 1347 | int v3; 1348 | int v4; 1349 | char v5; 1350 | char *v6; 1351 | int v7; 1352 | char *i; 1353 | int v9; 1354 | int v10; 1355 | int v11; 1356 | v6 = 0; 1357 | v10 = Curl_urldecode(a1, a2, 0, &v6, &v7, 2); 1358 | if ( !v6 || v10 ) 1359 | return 0; 1360 | v11 = Curl_cmalloc(2 * v7 + 1); 1361 | if ( v11 ) 1362 | { 1363 | v9 = 0; 1364 | for ( i = v6; ; ++i ) 1365 | { 1366 | v5 = *i; 1367 | if ( !*i ) 1368 | break; 1369 | if ( v5 < 33 || v5 == 127 || v5 == 39 || v5 == 34 || v5 == 92 ) 1370 | { 1371 | v3 = v9++; 1372 | *(_BYTE *)(v11 + v3) = 92; 1373 | } 1374 | v4 = v9++; 1375 | *(_BYTE *)(v11 + v4) = v5; 1376 | } 1377 | *(_BYTE *)(v11 + v9) = 0; 1378 | } 1379 | Curl_cfree(v6); 1380 | return v11; 1381 | } 1382 | ///// 1383 | __fastcall Curl_doh(int a1, const char *a2, int a3, _DWORD *a4) 1384 | { 1385 | int i; 1386 | int *v6; 1387 | v6 = *(int **)a1; 1388 | *a4 = 1; 1389 | memset(v6 + 70, 0, 0x448u); 1390 | *(_DWORD *)(a1 + 1220) = *(_DWORD *)(a1 + 1220) & 0xFFFFFFFB | 4; 1391 | v6[342] = (int)a2; 1392 | v6[343] = a3; 1393 | v6[70] = (int)curl_slist_append(0, (int)"Content-Type: application/dns-message"); 1394 | if ( !v6[70] ) 1395 | goto LABEL_9; 1396 | if ( *(_DWORD *)(a1 + 1264) != 2 ) 1397 | { 1398 | if ( dohprobe((int)v6, (int)(v6 + 71), 1, a2, v6[659], v6[30], v6[70]) ) 1399 | goto LABEL_9; 1400 | ++v6[341]; 1401 | } 1402 | if ( *(_DWORD *)(a1 + 1264) == 1 ) 1403 | return 0; 1404 | if ( !dohprobe((int)v6, (int)(v6 + 206), 28, a2, v6[659], v6[30], v6[70]) ) 1405 | { 1406 | ++v6[341]; 1407 | return 0; 1408 | } 1409 | LABEL_9: 1410 | curl_slist_free_all((_DWORD *)v6[70]); 1411 | v6[70] = 0; 1412 | for ( i = 0; i < 2; ++i ) 1413 | Curl_close(&v6[135 * i + 71]); 1414 | return 0; 1415 | } 1416 | ///// 1417 | __fastcall skipqname(int a1, unsigned int a2, _DWORD *a3) 1418 | { 1419 | unsigned __int8 v4; 1420 | while ( 1 ) 1421 | { 1422 | if ( a2 < *a3 + 1 ) 1423 | return 2; 1424 | v4 = *(_BYTE *)(a1 + *a3); 1425 | if ( (v4 & 0xC0) == 192 ) 1426 | break; 1427 | if ( (v4 & 0xC0) != 0 ) 1428 | return 1; 1429 | if ( a2 < *a3 + (unsigned int)v4 + 1 ) 1430 | return 2; 1431 | *a3 += v4 + 1; 1432 | if ( !v4 ) 1433 | return 0; 1434 | } 1435 | if ( a2 < *a3 + 2 ) 1436 | return 2; 1437 | *a3 += 2; 1438 | return 0; 1439 | } 1440 | ///// 1441 | __fastcall store_aaaa(int a1, int a2, int a3) 1442 | { 1443 | _DWORD *v4; 1444 | if ( *(int *)(a3 + 544) < 24 ) 1445 | { 1446 | v4 = (_DWORD *)(a3 + 20 * *(_DWORD *)(a3 + 544) + 64); 1447 | *v4 = 28; 1448 | memcpy(v4 + 1, (const void *)(a1 + a2), 0x10u); 1449 | ++*(_DWORD *)(a3 + 544); 1450 | } 1451 | return 0; 1452 | } 1453 | ///// 1454 | __fastcall bindlocal(int *a1, int a2, int a3, int a4) 1455 | { 1456 | int result; 1457 | const char *v5; 1458 | size_t v6; 1459 | int v7; 1460 | const char *v8; 1461 | size_t v9; 1462 | size_t v10; 1463 | int v11; 1464 | char *v12; 1465 | int v13; 1466 | int v14; 1467 | int v15; 1468 | char *v16; 1469 | char *v17; 1470 | char v19; 1471 | char v20; 1472 | uint16_t v21; 1473 | int *v22; 1474 | socklen_t v23; 1475 | socklen_t len; 1476 | int v25; 1477 | char *s; 1478 | int v27; 1479 | char *nptr; 1480 | int v29; 1481 | struct sockaddr *addr; 1482 | char *v31; 1483 | char *v32; 1484 | int v33; 1485 | int v34; 1486 | int v35; 1487 | char v36[128]; 1488 | struct sockaddr v37[8]; 1489 | int v38; 1490 | char v39[252]; 1491 | v29 = *a1; 1492 | addr = (struct sockaddr *)v36; 1493 | len = 0; 1494 | v31 = v36; 1495 | v32 = v36; 1496 | v22 = 0; 1497 | v21 = *(_WORD *)(v29 + 1464); 1498 | v25 = *(_DWORD *)(v29 + 1468); 1499 | s = *(char **)(v29 + 2396); 1500 | if ( !s && !v21 ) 1501 | return 0; 1502 | memset(v36, 0, sizeof(v36)); 1503 | if ( s && strlen(s) < 0xFF ) 1504 | { 1505 | v38 = 0; 1506 | memset(v39, 0, sizeof(v39)); 1507 | v27 = 0; 1508 | v19 = 0; 1509 | v20 = 0; 1510 | v5 = if_prefix_8775[0]; 1511 | v6 = strlen(if_prefix_8775[0]); 1512 | if ( strncmp(v5, s, v6) ) 1513 | { 1514 | v8 = host_prefix_8776; 1515 | v9 = strlen(host_prefix_8776); 1516 | if ( !strncmp(v8, s, v9) ) 1517 | { 1518 | s += strlen(host_prefix_8776); 1519 | v20 = 1; 1520 | } 1521 | } 1522 | else 1523 | { 1524 | s += strlen(if_prefix_8775[0]); 1525 | v19 = 1; 1526 | } 1527 | if ( v20 != 1 ) 1528 | { 1529 | v10 = strlen(s); 1530 | if ( !setsockopt(a2, 0xFFFF, 25, s, v10 + 1) ) 1531 | return 0; 1532 | v11 = Curl_if2ip(a3, a4, a1[189], s, (int)&v38, 256); 1533 | if ( v11 == 1 ) 1534 | return 1; 1535 | if ( v11 ) 1536 | { 1537 | if ( v11 == 2 ) 1538 | { 1539 | v19 = 1; 1540 | Curl_infof(v29, "Local Interface %s is ip %s using address family %i\n", (int)s, (int)&v38); 1541 | v27 = 1; 1542 | } 1543 | } 1544 | else if ( v19 ) 1545 | { 1546 | Curl_failf(v29, "Couldn't bind to interface '%s'", (int)s, v7); 1547 | return 45; 1548 | } 1549 | } 1550 | if ( v19 != 1 ) 1551 | { 1552 | v33 = a1[316]; 1553 | if ( a3 == 2 ) 1554 | { 1555 | a1[316] = 1; 1556 | } 1557 | else if ( a3 == 10 ) 1558 | { 1559 | a1[316] = 2; 1560 | } 1561 | v34 = Curl_resolv(a1, s, 0, 0, &v22); 1562 | if ( v34 == 1 ) 1563 | Curl_resolver_wait_resolv((int)a1, &v22); 1564 | a1[316] = v33; 1565 | if ( v22 ) 1566 | { 1567 | Curl_printable_address(*v22, (char *)&v38, 0x100u); 1568 | Curl_infof(v29, "Name '%s' family %i resolved to '%s' family %i\n", (int)s, a3); 1569 | Curl_resolv_unlock(v29, v22); 1570 | if ( a3 != *(_DWORD *)(*v22 + 4) ) 1571 | return 1; 1572 | v27 = 1; 1573 | } 1574 | else 1575 | { 1576 | v27 = -1; 1577 | } 1578 | } 1579 | if ( v27 > 0 ) 1580 | { 1581 | if ( a3 == 10 ) 1582 | { 1583 | nptr = strchr((const char *)&v38, 37); 1584 | if ( nptr ) 1585 | { 1586 | v12 = nptr++; 1587 | *v12 = 0; 1588 | } 1589 | if ( inet_pton(10, (const char *)&v38, v32 + 8) > 0 ) 1590 | { 1591 | *(_WORD *)v32 = 10; 1592 | *((_WORD *)v32 + 1) = htons(v21); 1593 | if ( nptr ) 1594 | { 1595 | v13 = atoi(nptr); 1596 | *((_DWORD *)v32 + 6) = v13; 1597 | } 1598 | } 1599 | len = 28; 1600 | } 1601 | else if ( a3 == 2 && inet_pton(2, (const char *)&v38, v31 + 4) > 0 ) 1602 | { 1603 | *(_WORD *)v31 = 2; 1604 | *((_WORD *)v31 + 1) = htons(v21); 1605 | len = 16; 1606 | } 1607 | } 1608 | if ( v27 > 0 ) 1609 | goto LABEL_50; 1610 | *(_WORD *)(v29 + 3932) &= 0xEFFFu; 1611 | Curl_failf(v29, "Couldn't bind to '%s'", (int)s, v7); 1612 | result = 45; 1613 | } 1614 | else 1615 | { 1616 | if ( a3 == 10 ) 1617 | { 1618 | *(_WORD *)v32 = 10; 1619 | *((_WORD *)v32 + 1) = htons(v21); 1620 | len = 28; 1621 | } 1622 | else if ( a3 == 2 ) 1623 | { 1624 | *(_WORD *)v31 = 2; 1625 | *((_WORD *)v31 + 1) = htons(v21); 1626 | len = 16; 1627 | } 1628 | LABEL_50: 1629 | while ( bind(a2, addr, len) < 0 ) 1630 | { 1631 | if ( --v25 <= 0 ) 1632 | { 1633 | v35 = *_errno_location(); 1634 | *(_DWORD *)(v29 + 3268) = v35; 1635 | v17 = Curl_strerror(v35, (char *)&v38, 256); 1636 | Curl_failf(v29, "bind failed with errno %d: %s", v35, (int)v17); 1637 | return 45; 1638 | } 1639 | Curl_infof(v29, "Bind to local port %hu failed, trying next\n", v21++, v14); 1640 | if ( addr->sa_family == 2 ) 1641 | *((_WORD *)v31 + 1) = ntohs(v21); 1642 | else 1643 | *((_WORD *)v32 + 1) = ntohs(v21); 1644 | } 1645 | v23 = 128; 1646 | memset(v37, 0, sizeof(v37)); 1647 | if ( getsockname(a2, v37, &v23) >= 0 ) 1648 | { 1649 | Curl_infof(v29, "Local port: %hu\n", v21, v15); 1650 | a1[305] = a1[305] & 0xFFFFFEFF | 0x100; 1651 | result = 0; 1652 | } 1653 | else 1654 | { 1655 | v35 = *_errno_location(); 1656 | *(_DWORD *)(v29 + 3268) = v35; 1657 | v16 = Curl_strerror(v35, (char *)&v38, 256); 1658 | Curl_failf(v29, "getsockname() failed with errno %d: %s", v35, (int)v16); 1659 | result = 45; 1660 | } 1661 | } 1662 | return result; 1663 | } 1664 | ///// 1665 | __fastcall singleipconnect(int *a1, int a2, int a3) 1666 | { 1667 | int result; 1668 | int v4; 1669 | int *v5; 1670 | char *v6; 1671 | bool v7; 1672 | int v8; 1673 | int v9; 1674 | int v10; 1675 | int *v11; 1676 | int v12; 1677 | __time_t v13; 1678 | int v14; 1679 | int v15; 1680 | char *v16; 1681 | __time_t v17[2]; 1682 | int v18; 1683 | int *v19; 1684 | char v20; 1685 | bool v21; 1686 | int v22; 1687 | int v23; 1688 | int v24; 1689 | int v25; 1690 | int v26; 1691 | int *v28; 1692 | int *v29; 1693 | int v30[3]; 1694 | unsigned int v31; 1695 | struct sockaddr v32[8]; 1696 | char v33[48]; 1697 | char v34[256]; 1698 | v19 = a1; 1699 | v18 = a2; 1700 | v25 = -1; 1701 | v26 = 0; 1702 | v20 = 0; 1703 | v28 = (int *)*a1; 1704 | v24 = 1; 1705 | v29 = &a1[a3 + 260]; 1706 | *v29 = -1; 1707 | v27 = Curl_socket(v19, v18, (char *)v30, &v22); 1708 | if ( v27 ) 1709 | return v27; 1710 | if ( (unsigned __int8)Curl_addr2string((uint16_t *)v32, v31, v33, &v23) != 1 ) 1711 | { 1712 | v4 = *_errno_location(); 1713 | v5 = _errno_location(); 1714 | v6 = Curl_strerror(*v5, v34, 256); 1715 | Curl_failf((int)v28, "sa_addr inet_ntop() failed with errno %d: %s", v4, (int)v6); 1716 | Curl_closesocket((int)v19, v22); 1717 | return 0; 1718 | } 1719 | Curl_infof((int)v28, " Trying %s:%ld...\n", (int)v33, v23); 1720 | v7 = (v30[0] == 2 || v30[0] == 10) && v30[1] == 2; 1721 | v21 = v7; 1722 | if ( v7 && (v28[702] & 0x10000000) != 0 ) 1723 | tcpnodelay(v19, v22); 1724 | if ( v21 && (v28[702] & 0x100000) != 0 ) 1725 | tcpkeepalive(v28, v22); 1726 | if ( v28[376] ) 1727 | { 1728 | Curl_set_in_callback((int)v28, 1); 1729 | v26 = ((int (__fastcall *)(int, int, _DWORD))v28[376])(v28[377], v22, 0); 1730 | Curl_set_in_callback((int)v28, 0); 1731 | if ( v26 == 2 ) 1732 | { 1733 | v20 = 1; 1734 | } 1735 | else if ( v26 ) 1736 | { 1737 | Curl_closesocket((int)v19, v22); 1738 | return 42; 1739 | } 1740 | } 1741 | if ( (v30[0] == 2 || v30[0] == 10) 1742 | && (v8 = v22, v9 = v30[0], v10 = Curl_ipv6_scope((int)v32), (v27 = bindlocal(v19, v8, v9, v10)) != 0) ) 1743 | { 1744 | Curl_closesocket((int)v19, v22); 1745 | if ( v27 == 1 ) 1746 | result = 7; 1747 | else 1748 | result = v27; 1749 | } 1750 | else 1751 | { 1752 | curlx_nonblock(v22, 1); 1753 | v11 = v19; 1754 | Curl_now(v17); 1755 | v13 = v17[1]; 1756 | v11[307] = v17[0]; 1757 | v11[308] = v13; 1758 | if ( v19[309] >= 2 ) 1759 | { 1760 | Curl_expire((int)v28, v12, *((_QWORD *)v19 + 155), 3); 1761 | Curl_expire((int)v28, v14, *((_QWORD *)v19 + 156), 4); 1762 | } 1763 | if ( v20 == 1 || v19[190] == 4 ) 1764 | { 1765 | *v29 = v22; 1766 | result = 0; 1767 | } 1768 | else 1769 | { 1770 | if ( (v19[305] & 0x40) != 0 && setsockopt(v22, 6, 30, &v24, 4u) < 0 ) 1771 | Curl_infof((int)v28, "Failed to enable TCP Fast Open on fd %d\n", v22, v15); 1772 | v25 = connect(v22, v32, v31); 1773 | if ( v25 == -1 ) 1774 | v26 = *_errno_location(); 1775 | if ( v25 == -1 ) 1776 | { 1777 | if ( v26 == 11 || v26 == 150 ) 1778 | { 1779 | v27 = 0; 1780 | } 1781 | else 1782 | { 1783 | v16 = Curl_strerror(v26, v34, 256); 1784 | Curl_infof((int)v28, "Immediate connect fail for %s: %s\n", (int)v33, (int)v16); 1785 | v28[817] = v26; 1786 | Curl_closesocket((int)v19, v22); 1787 | v27 = 7; 1788 | } 1789 | } 1790 | if ( !v27 ) 1791 | *v29 = v22; 1792 | result = v27; 1793 | } 1794 | } 1795 | return result; 1796 | } 1797 | ///// 1798 | __fastcall cookie_output(int a1, int a2, const char *a3) 1799 | { 1800 | int v4; 1801 | size_t v5; 1802 | char v9; 1803 | unsigned __int8 v10; 1804 | _DWORD *j; 1805 | struct _IO_FILE *s; 1806 | char *name; 1807 | unsigned int i; 1808 | size_t k; 1809 | size_t nmemb; 1810 | _DWORD *base; 1811 | const char *v18; 1812 | char v19[12]; 1813 | v9 = 0; 1814 | name = 0; 1815 | v10 = 0; 1816 | if ( !a2 ) 1817 | return 0; 1818 | remove_expired(a2); 1819 | if ( strcmp("-", a3) ) 1820 | { 1821 | if ( Curl_rand_hex(a1, v19, 9u) ) 1822 | return 2; 1823 | name = (char *)curl_maprintf("%s.%s.tmp", (int)a3, (int)v19, v4); 1824 | if ( !name ) 1825 | return 1; 1826 | s = (struct _IO_FILE *)fopen64(name, "w"); 1827 | if ( !s ) 1828 | goto LABEL_30; 1829 | fwrite( 1830 | "# Netscape HTTP Cookie File\n" 1831 | "# https: 1832 | "# This file was generated by libcurl! Edit at your own risk.\n" 1833 | "\n", 1834 | 1u, 1835 | 0x88u, 1836 | s); 1837 | } 1838 | else 1839 | { 1840 | s = stdout; 1841 | v9 = 1; 1842 | fwrite( 1843 | "# Netscape HTTP Cookie File\n" 1844 | "# https: 1845 | "# This file was generated by libcurl! Edit at your own risk.\n" 1846 | "\n", 1847 | 1u, 1848 | 0x88u, 1849 | stdout); 1850 | } 1851 | if ( *(_DWORD *)(a2 + 1032) ) 1852 | { 1853 | nmemb = 0; 1854 | base = (_DWORD *)Curl_ccalloc(1, 4 * *(_DWORD *)(a2 + 1032)); 1855 | if ( !base ) 1856 | goto LABEL_30; 1857 | for ( i = 0; i < 0x100; ++i ) 1858 | { 1859 | for ( j = *(_DWORD **)(a2 + 4 * i); j; j = (_DWORD *)*j ) 1860 | { 1861 | if ( j[5] ) 1862 | { 1863 | v5 = nmemb++; 1864 | base[v5] = j; 1865 | } 1866 | } 1867 | } 1868 | qsort(base, nmemb, 4u, (__compar_fn_t)cookie_sort_ct); 1869 | for ( k = 0; k < nmemb; ++k ) 1870 | { 1871 | v18 = (const char *)get_netscape_format(base[k]); 1872 | if ( !v18 ) 1873 | { 1874 | curl_mfprintf((int)s, "#\n# Fatal libcurl error\n"); 1875 | Curl_cfree(base); 1876 | goto LABEL_30; 1877 | } 1878 | curl_mfprintf((int)s, "%s\n", v18); 1879 | Curl_cfree(v18); 1880 | } 1881 | Curl_cfree(base); 1882 | } 1883 | if ( v9 == 1 ) 1884 | goto LABEL_31; 1885 | fclose(s); 1886 | s = 0; 1887 | if ( !Curl_rename(name, a3) ) 1888 | goto LABEL_31; 1889 | unlink(name); 1890 | LABEL_30: 1891 | v10 = 1; 1892 | LABEL_31: 1893 | if ( s ) 1894 | { 1895 | if ( v9 != 1 ) 1896 | fclose(s); 1897 | } 1898 | Curl_cfree(name); 1899 | return v10; 1900 | } 1901 | ///// 1902 | __fastcall dict_do(int *a1, _BYTE *a2) 1903 | { 1904 | int v2; 1905 | int v3; 1906 | const char *v4; 1907 | const char *v5; 1908 | int v7; 1909 | int v8; 1910 | int v9; 1911 | int v10; 1912 | const char *v11; 1913 | const char *v12; 1914 | const char *v13; 1915 | const char *v14; 1916 | const char *v15; 1917 | int i; 1918 | char *v17; 1919 | char *v18; 1920 | int v19; 1921 | _DWORD *v20; 1922 | int v21; 1923 | char *s; 1924 | char *v23; 1925 | const char *v24; 1926 | const char *v25; 1927 | const char *v26; 1928 | v14 = 0; 1929 | v15 = 0; 1930 | v20 = (_DWORD *)*a1; 1931 | v21 = a1[258]; 1932 | s = *(char **)(*a1 + 3856); 1933 | *a2 = 1; 1934 | if ( Curl_strncasecompare(s, "/MATCH:", 7) 1935 | || Curl_strncasecompare(s, "/M:", 3) 1936 | || Curl_strncasecompare(s, "/FIND:", 6) ) 1937 | { 1938 | v12 = strchr(s, 58); 1939 | if ( v12 ) 1940 | { 1941 | v14 = strchr(++v12, 58); 1942 | if ( v14 ) 1943 | { 1944 | v4 = v14++; 1945 | *v4 = 0; 1946 | v15 = strchr(v14, 58); 1947 | if ( v15 ) 1948 | { 1949 | v5 = v15++; 1950 | *v5 = 0; 1951 | v17 = strchr(v15, 58); 1952 | if ( v17 ) 1953 | *v17 = 0; 1954 | } 1955 | } 1956 | } 1957 | if ( !v12 || !*v12 ) 1958 | { 1959 | Curl_infof((int)v20, "lookup word is missing\n", v3, v2); 1960 | v12 = "default"; 1961 | } 1962 | if ( !v14 || !*v14 ) 1963 | v14 = "!"; 1964 | if ( !v15 || !*v15 ) 1965 | v15 = "."; 1966 | v25 = (const char *)unescape_word((int)v20, v12); 1967 | if ( !v25 ) 1968 | return 27; 1969 | v19 = Curl_sendf(v21, a1, "CLIENT libcurl 7.71.1\r\nMATCH %s %s %s\r\nQUIT\r\n", v14, v15, v25); 1970 | Curl_cfree(v25); 1971 | if ( v19 ) 1972 | goto LABEL_47; 1973 | goto LABEL_48; 1974 | } 1975 | if ( Curl_strncasecompare(s, "/DEFINE:", 8) 1976 | || Curl_strncasecompare(s, "/D:", 3) 1977 | || Curl_strncasecompare(s, "/LOOKUP:", 8) ) 1978 | { 1979 | v13 = strchr(s, 58); 1980 | if ( v13 ) 1981 | { 1982 | v14 = strchr(++v13, 58); 1983 | if ( v14 ) 1984 | { 1985 | v11 = v14++; 1986 | *v11 = 0; 1987 | v18 = strchr(v14, 58); 1988 | if ( v18 ) 1989 | *v18 = 0; 1990 | } 1991 | } 1992 | if ( !v13 || !*v13 ) 1993 | { 1994 | Curl_infof((int)v20, "lookup word is missing\n", v10, v9); 1995 | v13 = "default"; 1996 | } 1997 | if ( !v14 || !*v14 ) 1998 | v14 = "!"; 1999 | v26 = (const char *)unescape_word((int)v20, v13); 2000 | if ( !v26 ) 2001 | return 27; 2002 | v19 = Curl_sendf(v21, a1, "CLIENT libcurl 7.71.1\r\nDEFINE %s %s\r\nQUIT\r\n", v14, v26); 2003 | Curl_cfree(v26); 2004 | if ( v19 ) 2005 | goto LABEL_47; 2006 | LABEL_48: 2007 | Curl_setup_transfer(v20, 0, -1LL, 0, -1); 2008 | return 0; 2009 | } 2010 | v23 = strchr(s, 47); 2011 | if ( v23 ) 2012 | { 2013 | v24 = v23 + 1; 2014 | for ( i = 0; v24[i]; ++i ) 2015 | { 2016 | if ( v24[i] == 58 ) 2017 | v24[i] = 32; 2018 | } 2019 | v19 = Curl_sendf(v21, a1, "CLIENT libcurl 7.71.1\r\n%s\r\nQUIT\r\n", v24); 2020 | if ( v19 ) 2021 | { 2022 | LABEL_47: 2023 | Curl_failf((int)v20, "Failed sending DICT request", v8, v7); 2024 | return v19; 2025 | } 2026 | goto LABEL_48; 2027 | } 2028 | return 0; 2029 | } -------------------------------------------------------------------------------- /Dataset/SQLite.txt: -------------------------------------------------------------------------------- 1 | __cdecl isAlterableTable(_DWORD **a1, _DWORD *a2) 2 | { 3 | if ( sqlite3_strnicmp(*a2, "sqlite_", 7) && ((a2[9] & 0x1000) == 0 || !sqlite3ReadOnlyShadowTables(*a1)) ) 4 | return 0; 5 | sqlite3ErrorMsg((int)a1, (int)"table %s may not be altered", *a2); 6 | return 1; 7 | } 8 | ///// 9 | __cdecl renameReloadSchema(int a1, int a2) 10 | { 11 | int result; 12 | result = *(_DWORD *)(a1 + 8); 13 | if ( result ) 14 | { 15 | sqlite3ChangeCookie((_DWORD **)a1, a2); 16 | result = sqlite3VdbeAddParseSchemaOp(*(_DWORD **)(a1 + 8), a2, 0); 17 | if ( a2 != 1 ) 18 | result = sqlite3VdbeAddParseSchemaOp(*(_DWORD **)(a1 + 8), 1, 0); 19 | } 20 | return result; 21 | } 22 | ///// 23 | __cdecl sqlite3RenameTokenMap(int *a1, int a2, _DWORD *a3) 24 | { 25 | int v3; 26 | int (__cdecl *v5)(int); 27 | if ( *((_BYTE *)a1 + (_DWORD)(&off_E00CC - 229376)) != 3 ) 28 | { 29 | v5 = (int (__cdecl *)(int))sqlite3DbMallocZero(*a1, 0x10uLL); 30 | if ( v5 ) 31 | { 32 | *(_DWORD *)v5 = a2; 33 | v3 = a3[1]; 34 | *((_DWORD *)v5 + 1) = *a3; 35 | *((_DWORD *)v5 + 2) = v3; 36 | *((_DWORD *)v5 + 3) = *(int (__cdecl **)(int))((char *)&off_E0114[-229376] + (_DWORD)a1); 37 | *(int (__cdecl **)(int))((char *)&off_E0114[-229376] + (_DWORD)a1) = v5; 38 | } 39 | } 40 | return a2; 41 | } 42 | ///// 43 | __cdecl sqlite3RenameTokenRemap(int a1, int a2, int a3) 44 | { 45 | _DWORD *result; 46 | _DWORD *i; 47 | result = *(int (__cdecl **)(int))((char *)&off_E0114[-229376] + a1); 48 | for ( i = result; i; i = result ) 49 | { 50 | if ( a3 == *i ) 51 | { 52 | result = i; 53 | *i = a2; 54 | return result; 55 | } 56 | result = (_DWORD *)i[3]; 57 | } 58 | return result; 59 | } 60 | ///// 61 | __cdecl renameWalkWith(int *a1, int a2) 62 | { 63 | int i; 64 | _DWORD *v4; 65 | int v5; 66 | _DWORD *s[8]; 67 | unsigned int v7; 68 | v7 = __readgsdword(0x14u); 69 | v4 = *(_DWORD **)(a2 + 64); 70 | if ( v4 ) 71 | { 72 | for ( i = 0; i < *v4; ++i ) 73 | { 74 | v5 = v4[4 * i + 4]; 75 | memset(s, 0, sizeof(s)); 76 | s[0] = (_DWORD *)*a1; 77 | sqlite3SelectPrep(s[0], v5, (int)s); 78 | sqlite3WalkSelect((int)a1, v5); 79 | sqlite3RenameExprlistUnmap(*a1, (int *)v4[4 * i + 3]); 80 | } 81 | } 82 | return __readgsdword(0x14u) ^ v7; 83 | } 84 | ///// 85 | __cdecl renameUnmapSelectCb(int *a1, _DWORD *a2) 86 | { 87 | int i; 88 | int j; 89 | int v5; 90 | _DWORD *v6; 91 | _DWORD *v7; 92 | v5 = *a1; 93 | if ( *(_DWORD *)(*a1 + 36) ) 94 | return 2; 95 | if ( (a2[1] & 0x200000) != 0 ) 96 | return 1; 97 | if ( a2[7] ) 98 | { 99 | v6 = (_DWORD *)a2[7]; 100 | for ( i = 0; i < *v6; ++i ) 101 | { 102 | if ( v6[4 * i + 2] ) 103 | { 104 | if ( (v6[4 * i + 3] & 0x300) == 0 ) 105 | sqlite3RenameTokenRemap(v5, 0, v6[4 * i + 2]); 106 | } 107 | } 108 | } 109 | if ( a2[8] ) 110 | { 111 | v7 = (_DWORD *)a2[8]; 112 | for ( j = 0; j < *v7; ++j ) 113 | { 114 | sqlite3RenameTokenRemap(v5, 0, v7[17 * j + 4]); 115 | if ( sqlite3WalkExpr((int)a1, (_DWORD *)v7[17 * j + 13]) ) 116 | return 2; 117 | unmapColumnIdlistNames(v5, (_DWORD *)v7[17 * j + 14]); 118 | } 119 | } 120 | renameWalkWith(a1, (int)a2); 121 | return 0; 122 | } 123 | ///// 124 | __cdecl sqlite3RenameExprUnmap(int a1, _DWORD *a2) 125 | { 126 | char v3; 127 | int s[7]; 128 | unsigned int v5; 129 | v5 = __readgsdword(0x14u); 130 | v3 = *(_BYTE *)(a1 + 204); 131 | memset(s, 0, sizeof(s)); 132 | s[0] = a1; 133 | s[1] = (int)renameUnmapExprCb; 134 | s[2] = (int)renameUnmapSelectCb; 135 | *(_BYTE *)(a1 + 204) = 3; 136 | sqlite3WalkExpr((int)s, a2); 137 | *(_BYTE *)(a1 + 204) = v3; 138 | return __readgsdword(0x14u) ^ v5; 139 | } 140 | ///// 141 | __cdecl renameTokenFind(int a1, _DWORD *a2, int a3) 142 | { 143 | _DWORD *result; 144 | int i; 145 | _DWORD *v5; 146 | for ( i = a1 + 276; ; i = *(_DWORD *)i + 12 ) 147 | { 148 | result = *(_DWORD **)i; 149 | if ( !*(_DWORD *)i ) 150 | break; 151 | if ( a3 == **(_DWORD **)i ) 152 | { 153 | v5 = *(_DWORD **)i; 154 | *(_DWORD *)i = *(_DWORD *)(*(_DWORD *)i + 12); 155 | v5[3] = *a2; 156 | *a2 = v5; 157 | result = a2; 158 | ++a2[1]; 159 | return result; 160 | } 161 | } 162 | return result; 163 | } 164 | ///// 165 | __cdecl renameColumnExprCb(int *a1, int a2) 166 | { 167 | _DWORD *v3; 168 | v3 = (_DWORD *)a1[6]; 169 | if ( *(_BYTE *)a2 == 77 && *(__int16 *)(a2 + 32) == v3[2] && *(_DWORD *)(*a1 + 120) == v3[3] 170 | || *(_BYTE *)a2 == 0xA4 && *(__int16 *)(a2 + 32) == v3[2] && v3[3] == *(_DWORD *)(a2 + 44) ) 171 | { 172 | renameTokenFind(*a1, v3, a2); 173 | } 174 | return 0; 175 | } 176 | ///// 177 | __cdecl renameColumnIdlistNames(int a1, _DWORD *a2, _DWORD *a3, int a4) 178 | { 179 | int i; 180 | int v5; 181 | if ( a3 ) 182 | { 183 | for ( i = 0; i < a3[1]; ++i ) 184 | { 185 | v5 = *(_DWORD *)(8 * i + *a3); 186 | if ( !sqlite3_stricmp(v5, a4) ) 187 | renameTokenFind(a1, a2, v5); 188 | } 189 | } 190 | } 191 | ///// 192 | __cdecl renameWalkTrigger(int a1, int a2) 193 | { 194 | int result; 195 | int i; 196 | int **v4; 197 | sqlite3WalkExpr(a1, *(_DWORD **)(a2 + 12)); 198 | result = *(_DWORD *)(a2 + 28); 199 | for ( i = result; i; i = result ) 200 | { 201 | sqlite3WalkSelect(a1, *(_DWORD *)(i + 8)); 202 | sqlite3WalkExpr(a1, *(_DWORD **)(i + 20)); 203 | sqlite3WalkExprList(a1, *(int **)(i + 24)); 204 | if ( *(_DWORD *)(i + 32) ) 205 | { 206 | v4 = *(int ***)(i + 32); 207 | sqlite3WalkExprList(a1, *v4); 208 | sqlite3WalkExprList(a1, v4[2]); 209 | sqlite3WalkExpr(a1, v4[3]); 210 | sqlite3WalkExpr(a1, v4[1]); 211 | } 212 | result = *(_DWORD *)(i + 40); 213 | } 214 | return result; 215 | } 216 | ///// 217 | __cdecl renameParseCleanup(int a1) 218 | { 219 | _DWORD *v2; 220 | int v3; 221 | v2 = *(_DWORD **)a1; 222 | if ( *(_DWORD *)(a1 + 8) ) 223 | sqlite3VdbeFinalize(*(_DWORD *)(a1 + 8)); 224 | sqlite3DeleteTable(v2, *(int *)((char *)&off_E00E8 + a1 - 917504)); 225 | while ( 1 ) 226 | { 227 | v3 = *(int *)((char *)&off_E00EC + a1 - 917504); 228 | if ( !v3 ) 229 | break; 230 | *(void **)((char *)&off_E00EC + a1 - 917504) = *(void **)(v3 + 20); 231 | sqlite3FreeIndex(v2, v3); 232 | } 233 | sqlite3DeleteTrigger(v2, *(int *)((char *)&off_E00F0 + a1 - 917504)); 234 | sqlite3DbFree(v2, *(int (__cdecl **)(int, int, int, char))(a1 + 4)); 235 | renameTokenFree(v2, *(int *)((char *)&off_E0114[-229376] + a1)); 236 | return sqlite3ParserReset((int *)a1); 237 | } 238 | ///// 239 | __cdecl renameTableSelectCb(int *a1, int a2) 240 | { 241 | int i; 242 | _DWORD *v4; 243 | _DWORD *v5; 244 | v4 = (_DWORD *)a1[6]; 245 | v5 = *(_DWORD **)(a2 + 32); 246 | if ( (*(_DWORD *)(a2 + 4) & 0x200000) != 0 ) 247 | return 1; 248 | if ( !v5 ) 249 | return 2; 250 | for ( i = 0; i < *v5; ++i ) 251 | { 252 | if ( v5[17 * i + 6] == v4[3] ) 253 | renameTokenFind(*a1, v4, v5[17 * i + 4]); 254 | } 255 | renameWalkWith(a1, a2); 256 | return 0; 257 | } 258 | ///// 259 | __cdecl analyzeDatabase(int *a1, int a2) 260 | { 261 | int **i; 262 | int v4; 263 | int v5; 264 | int v6; 265 | int v7; 266 | v4 = *(_DWORD *)(16 * a2 + *(_DWORD *)(*a1 + 16) + 12); 267 | sqlite3BeginWriteOperation((int)a1, 0, a2); 268 | v5 = a1[10]; 269 | a1[10] = v5 + 3; 270 | openStatTable(a1, a2, v5, 0); 271 | v6 = a1[11] + 1; 272 | v7 = a1[10]; 273 | for ( i = *(int ***)(v4 + 16); i; i = (int **)*i ) 274 | analyzeOneTable(a1, i[2], 0, v5, v6, v7); 275 | return loadAnalysis(a1, a2); 276 | } 277 | ///// 278 | __cdecl decodeIntArray(unsigned __int8 *a1, int a2, int a3, int a4, int a5) 279 | { 280 | int result; 281 | int i; 282 | int v8; 283 | int v9; 284 | int v10; 285 | for ( i = 0; *a1 && i < a2; ++i ) 286 | { 287 | v8 = 0; 288 | while ( 1 ) 289 | { 290 | v10 = (char)*a1; 291 | if ( v10 <= 47 || v10 > 57 ) 292 | break; 293 | v8 = 10 * v8 + v10 - 48; 294 | ++a1; 295 | } 296 | *(_WORD *)(a4 + 2 * i) = sqlite3LogEst((unsigned int)v8); 297 | if ( *a1 == 32 ) 298 | ++a1; 299 | } 300 | *(_BYTE *)(a5 + 55) &= 0xFBu; 301 | *(_BYTE *)(a5 + 55) &= 0xBFu; 302 | while ( 1 ) 303 | { 304 | result = *a1; 305 | if ( !(_BYTE)result ) 306 | break; 307 | if ( sqlite3_strglob("unordered*", a1) ) 308 | { 309 | if ( sqlite3_strglob("sz=[0-9]*", a1) ) 310 | { 311 | if ( !sqlite3_strglob("noskipscan*", a1) ) 312 | *(_BYTE *)(a5 + 55) |= 0x40u; 313 | } 314 | else 315 | { 316 | v9 = sqlite3Atoi(a1 + 3); 317 | if ( v9 <= 1 ) 318 | v9 = 2; 319 | *(_WORD *)(a5 + 48) = sqlite3LogEst(v9); 320 | } 321 | } 322 | else 323 | { 324 | *(_BYTE *)(a5 + 55) |= 4u; 325 | } 326 | while ( *a1 && *a1 != 32 ) 327 | ++a1; 328 | while ( *a1 == 32 ) 329 | ++a1; 330 | } 331 | return result; 332 | } 333 | ///// 334 | __cdecl sqlite3AnalysisLoad(_DWORD *a1, int a2) 335 | { 336 | _DWORD *i; 337 | _DWORD *j; 338 | _DWORD *k; 339 | int v6; 340 | int v7; 341 | int (__cdecl *v8)(int, int, int, char); 342 | int v9; 343 | _DWORD *v10; 344 | _BYTE *v11; 345 | unsigned int v12; 346 | v12 = __readgsdword(0x14u); 347 | v6 = 0; 348 | v7 = *(_DWORD *)(16 * a2 + a1[4] + 12); 349 | for ( i = *(_DWORD **)(v7 + 16); i; i = (_DWORD *)*i ) 350 | *(_DWORD *)(i[2] + 36) &= 0xFFFFFFEF; 351 | for ( j = *(_DWORD **)(v7 + 32); j; j = (_DWORD *)*j ) 352 | *(_BYTE *)(j[2] + 55) &= 0x7Fu; 353 | v10 = a1; 354 | v11 = *(_BYTE **)(16 * a2 + a1[4]); 355 | if ( sqlite3FindTable((int)a1, "sqlite_stat1", v11) ) 356 | { 357 | v8 = (int (__cdecl *)(int, int, int, char))sqlite3MPrintf( 358 | (int)a1, 359 | (int)"SELECT tbl,idx,stat FROM %Q.sqlite_stat1", 360 | v11); 361 | if ( v8 ) 362 | { 363 | v6 = sqlite3_exec(a1, v8, analysisLoader, &v10, 0); 364 | sqlite3DbFree(a1, v8); 365 | } 366 | else 367 | { 368 | v6 = 7; 369 | } 370 | } 371 | for ( k = *(_DWORD **)(v7 + 32); k; k = (_DWORD *)*k ) 372 | { 373 | v9 = k[2]; 374 | if ( *(char *)(v9 + 55) >= 0 ) 375 | sqlite3DefaultRowEst(v9); 376 | } 377 | if ( v6 == 7 ) 378 | sqlite3OomFault((int)a1); 379 | return v6; 380 | } 381 | ///// 382 | __cdecl resolveAttachExpr(int *a1, _DWORD *a2) 383 | { 384 | _BOOL4 v3; 385 | v3 = 0; 386 | if ( a2 ) 387 | { 388 | if ( *(_BYTE *)a2 == 59 ) 389 | *(_BYTE *)a2 = 115; 390 | else 391 | v3 = sqlite3ResolveExprNames(a1, a2); 392 | } 393 | return v3; 394 | } 395 | ///// 396 | __cdecl sqlite3DbIsNamed(int a1, int a2, unsigned __int8 *a3) 397 | { 398 | return !sqlite3StrICmp(*(_BYTE **)(16 * a2 + *(_DWORD *)(a1 + 16)), a3) || !a2 && !sqlite3StrICmp("main", a3); 399 | } 400 | ///// 401 | __cdecl sqlite3FixExpr(int a1, int a2) 402 | { 403 | while ( a2 ) 404 | { 405 | if ( !*(_BYTE *)(a1 + 8) ) 406 | *(_DWORD *)(a2 + 4) |= 0x40000000u; 407 | if ( *(_BYTE *)a2 == 0x99 ) 408 | { 409 | if ( !*(_BYTE *)(**(_DWORD **)a1 + 161) ) 410 | { 411 | sqlite3ErrorMsg(*(_DWORD *)a1, (int)"%s cannot use variables", *(_DWORD *)(a1 + 16)); 412 | return 1; 413 | } 414 | *(_BYTE *)a2 = 119; 415 | } 416 | if ( (*(_DWORD *)(a2 + 4) & 0x804000) != 0 ) 417 | break; 418 | if ( (*(_DWORD *)(a2 + 4) & 0x800) != 0 ) 419 | { 420 | if ( sqlite3FixSelect(a1, *(_DWORD *)(a2 + 20)) ) 421 | return 1; 422 | } 423 | else if ( sqlite3FixExprList(a1, *(_DWORD **)(a2 + 20)) ) 424 | { 425 | return 1; 426 | } 427 | if ( sqlite3FixExpr(a1, *(_DWORD *)(a2 + 16)) ) 428 | return 1; 429 | a2 = *(_DWORD *)(a2 + 12); 430 | } 431 | return 0; 432 | } 433 | ///// 434 | __cdecl sqlite3AuthCheck(int a1, int a2, int a3, int a4, int a5) 435 | { 436 | int v6; 437 | int v7; 438 | v7 = *(_DWORD *)a1; 439 | if ( *(_BYTE *)(*(_DWORD *)a1 + 161) || *(_BYTE *)(a1 + 204) ) 440 | return 0; 441 | if ( !*(_DWORD *)(v7 + 328) ) 442 | return 0; 443 | v6 = (*(int (__cdecl **)(_DWORD, int, int, int, int, _DWORD))(v7 + 328))( 444 | *(_DWORD *)(v7 + 332), 445 | a2, 446 | a3, 447 | a4, 448 | a5, 449 | *(_DWORD *)(a1 + 244)); 450 | if ( v6 == 1 ) 451 | { 452 | sqlite3ErrorMsg(a1, (int)"not authorized"); 453 | *(_DWORD *)(a1 + 12) = 23; 454 | } 455 | else if ( v6 ) 456 | { 457 | if ( v6 != 2 ) 458 | { 459 | v6 = 1; 460 | sqliteAuthBadReturnCode(a1); 461 | } 462 | } 463 | return v6; 464 | } 465 | ///// 466 | __cdecl findBtree(int *a1, int a2, int a3) 467 | { 468 | int v4; 469 | int v5; 470 | int s; 471 | int (__cdecl *v7)(int, int, int, char); 472 | int v8; 473 | unsigned int v9; 474 | v9 = __readgsdword(0x14u); 475 | v5 = sqlite3FindDbName(a2, a3); 476 | if ( v5 == 1 ) 477 | { 478 | v4 = 0; 479 | memset(&s, 0, 0x118u); 480 | s = a2; 481 | if ( sqlite3OpenTempDatabase((int)&s) ) 482 | { 483 | sqlite3ErrorWithMsg(a1, v8, (int)"%s", v7); 484 | v4 = 1; 485 | } 486 | sqlite3DbFree(a1, v7); 487 | sqlite3ParserReset(&s); 488 | if ( v4 ) 489 | return 0; 490 | } 491 | if ( v5 >= 0 ) 492 | return *(_DWORD *)(16 * v5 + *(_DWORD *)(a2 + 16) + 4); 493 | sqlite3ErrorWithMsg(a1, 1, (int)"unknown database %s", a3); 494 | return 0; 495 | } 496 | ///// 497 | __cdecl sqlite3_backup_finish(int *a1) 498 | { 499 | int v2; 500 | int v3; 501 | _DWORD *i; 502 | int v5; 503 | int v6; 504 | if ( !a1 ) 505 | return 0; 506 | v5 = a1[5]; 507 | sqlite3_mutex_enter(*(_DWORD *)(v5 + 12)); 508 | sqlite3BtreeEnter(a1[6]); 509 | if ( *a1 ) 510 | sqlite3_mutex_enter(*(_DWORD *)(*a1 + 12)); 511 | if ( *a1 ) 512 | --*(_DWORD *)(a1[6] + 16); 513 | if ( a1[10] ) 514 | { 515 | v2 = sqlite3BtreePager(a1[6]); 516 | for ( i = (_DWORD *)sqlite3PagerBackupPtr(v2); a1 != (int *)*i; i = (_DWORD *)(*i + 44) ) 517 | ; 518 | *i = a1[11]; 519 | } 520 | sqlite3BtreeRollback(a1[1], 0, 0); 521 | if ( a1[7] == 101 ) 522 | v3 = 0; 523 | else 524 | v3 = a1[7]; 525 | v6 = v3; 526 | if ( *a1 ) 527 | { 528 | sqlite3Error((int *)*a1, v3); 529 | sqlite3LeaveMutexAndCloseZombie(*a1); 530 | } 531 | sqlite3BtreeLeave(a1[6]); 532 | if ( *a1 ) 533 | sub_6CA0(a1); 534 | sqlite3LeaveMutexAndCloseZombie(v5); 535 | return v6; 536 | } 537 | ///// 538 | __cdecl backupUpdate(_DWORD *a1, unsigned int a2, int a3) 539 | { 540 | _DWORD *result; 541 | int v4; 542 | do 543 | { 544 | if ( !isFatalError(a1[7]) && a2 < a1[4] ) 545 | { 546 | sqlite3_mutex_enter(*(_DWORD *)(*a1 + 12)); 547 | v4 = backupOnePage((int)a1, a2, a3, 1); 548 | sqlite3_mutex_leave(*(_DWORD *)(*a1 + 12)); 549 | if ( v4 ) 550 | a1[7] = v4; 551 | } 552 | result = (_DWORD *)a1[11]; 553 | a1 = result; 554 | } 555 | while ( result ); 556 | return result; 557 | } 558 | ///// 559 | __cdecl sqlite3BitvecDestroy(int a1) 560 | { 561 | int result; 562 | unsigned int i; 563 | if ( a1 ) 564 | { 565 | if ( *(_DWORD *)(a1 + 8) ) 566 | { 567 | for ( i = 0; i <= 0x7C; ++i ) 568 | sqlite3BitvecDestroy(*(_DWORD *)(a1 + 4 * i + 12)); 569 | } 570 | result = sub_6CA0(a1); 571 | } 572 | return result; 573 | } 574 | ///// 575 | __cdecl sqlite3BtreeEnter(int a1) 576 | { 577 | int result; 578 | result = *(unsigned __int8 *)(a1 + 9); 579 | if ( (_BYTE)result ) 580 | { 581 | ++*(_DWORD *)(a1 + 12); 582 | result = *(unsigned __int8 *)(a1 + 10); 583 | if ( !(_BYTE)result ) 584 | result = btreeLockCarefully(a1); 585 | } 586 | return result; 587 | } 588 | ///// 589 | __cdecl btreeLockCarefully(int a1) 590 | { 591 | int result; 592 | int i; 593 | int j; 594 | if ( sqlite3_mutex_try(*(_DWORD *)(*(_DWORD *)(a1 + 4) + 60)) ) 595 | { 596 | for ( i = *(_DWORD *)(a1 + 24); i; i = *(_DWORD *)(i + 24) ) 597 | { 598 | if ( *(_BYTE *)(i + 10) ) 599 | unlockBtreeMutex(i); 600 | } 601 | lockBtreeMutex(a1); 602 | result = *(_DWORD *)(a1 + 24); 603 | for ( j = result; j; j = result ) 604 | { 605 | if ( *(_DWORD *)(j + 12) ) 606 | lockBtreeMutex(j); 607 | result = *(_DWORD *)(j + 24); 608 | } 609 | } 610 | else 611 | { 612 | *(_DWORD *)(*(_DWORD *)(a1 + 4) + 4) = *(_DWORD *)a1; 613 | result = a1; 614 | *(_BYTE *)(a1 + 10) = 1; 615 | } 616 | return result; 617 | } 618 | ///// 619 | __cdecl sqlite3BtreeLeave(int a1) 620 | { 621 | int result; 622 | result = *(unsigned __int8 *)(a1 + 9); 623 | if ( (_BYTE)result ) 624 | { 625 | result = --*(_DWORD *)(a1 + 12); 626 | if ( !result ) 627 | result = unlockBtreeMutex(a1); 628 | } 629 | return result; 630 | } 631 | ///// 632 | __cdecl btreeLeaveAll(int a1) 633 | { 634 | int result; 635 | int i; 636 | int v3; 637 | for ( i = 0; ; ++i ) 638 | { 639 | result = *(_DWORD *)(a1 + 20); 640 | if ( i >= result ) 641 | break; 642 | v3 = *(_DWORD *)(16 * i + *(_DWORD *)(a1 + 16) + 4); 643 | if ( v3 ) 644 | sqlite3BtreeLeave(v3); 645 | } 646 | return result; 647 | } 648 | ///// 649 | __cdecl querySharedCacheTableLock(int a1, int a2, char a3) 650 | { 651 | __int16 v4; 652 | int i; 653 | int v6; 654 | v6 = *(_DWORD *)(a1 + 4); 655 | if ( !*(_BYTE *)(a1 + 9) ) 656 | return 0; 657 | if ( a1 != *(_DWORD *)(v6 + 80) && (*(_WORD *)(v6 + 24) & 0x40) != 0 ) 658 | return 262; 659 | for ( i = *(_DWORD *)(v6 + 76); ; i = *(_DWORD *)(i + 12) ) 660 | { 661 | if ( !i ) 662 | return 0; 663 | if ( a1 != *(_DWORD *)i && a2 == *(_DWORD *)(i + 4) && a3 != *(_BYTE *)(i + 8) ) 664 | break; 665 | } 666 | if ( a3 == 2 ) 667 | { 668 | v4 = *(_WORD *)(v6 + 24); 669 | LOBYTE(v4) = v4 | 0x80; 670 | *(_WORD *)(v6 + 24) = v4; 671 | } 672 | return 262; 673 | } 674 | ///// 675 | __cdecl invalidateIncrblobCursors(int a1, int a2, __int64 a3, int a4) 676 | { 677 | __int64 result; 678 | int i; 679 | if ( *(_BYTE *)(a1 + 11) ) 680 | { 681 | *(_BYTE *)(a1 + 11) = 0; 682 | for ( i = *(_DWORD *)(*(_DWORD *)(a1 + 4) + 8); i; i = *(_DWORD *)(i + 24) ) 683 | { 684 | if ( (*(_BYTE *)(i + 1) & 0x10) != 0 ) 685 | { 686 | *(_BYTE *)(a1 + 11) = 1; 687 | if ( a2 == *(_DWORD *)(i + 56) && (a4 || (result = a3 ^ *(_QWORD *)(i + 28)) == 0) ) 688 | *(_BYTE *)i = 1; 689 | } 690 | } 691 | } 692 | return result; 693 | } 694 | ///// 695 | __cdecl btreeReleaseAllCursorPages(int a1) 696 | { 697 | int result; 698 | int i; 699 | result = *(unsigned __int8 *)(a1 + 60); 700 | if ( (result & 0x80u) == 0 ) 701 | { 702 | for ( i = 0; i < *(char *)(a1 + 60); ++i ) 703 | releasePageNotNull(*(_DWORD *)(a1 + 4 * (i + 28))); 704 | releasePageNotNull(*(_DWORD *)(a1 + 108)); 705 | result = a1; 706 | *(_BYTE *)(a1 + 60) = -1; 707 | } 708 | return result; 709 | } 710 | ///// 711 | __cdecl saveCursorPosition(int a1) 712 | { 713 | int v2; 714 | if ( (*(_BYTE *)(a1 + 1) & 0x40) != 0 ) 715 | return 2835; 716 | if ( *(_BYTE *)a1 == 2 ) 717 | *(_BYTE *)a1 = 0; 718 | else 719 | *(_DWORD *)(a1 + 4) = 0; 720 | v2 = saveCursorKey(a1); 721 | if ( !v2 ) 722 | { 723 | btreeReleaseAllCursorPages(a1); 724 | *(_BYTE *)a1 = 3; 725 | } 726 | *(_BYTE *)(a1 + 1) &= 0xF1u; 727 | return v2; 728 | } 729 | ///// 730 | __cdecl saveAllCursors(int a1, int a2, int a3) 731 | { 732 | int i; 733 | for ( i = *(_DWORD *)(a1 + 8); i && (i == a3 || a2 && a2 != *(_DWORD *)(i + 56)); i = *(_DWORD *)(i + 24) ) 734 | ; 735 | if ( i ) 736 | return saveCursorsOnList(i, a2, a3); 737 | if ( a3 ) 738 | *(_BYTE *)(a3 + 1) &= 0xDFu; 739 | return 0; 740 | } 741 | ///// 742 | __cdecl btreeMoveto(int a1, unsigned __int8 *a2, __int64 a3, char a4, int *a5) 743 | { 744 | int v6; 745 | int v7; 746 | int v8; 747 | if ( !a2 ) 748 | { 749 | v7 = 0; 750 | LABEL_8: 751 | v6 = sqlite3BtreeMovetoUnpacked(a1, v7, a3, a4, a5); 752 | goto LABEL_9; 753 | } 754 | v8 = *(_DWORD *)(a1 + 104); 755 | v7 = sqlite3VdbeAllocUnpackedRecord(v8); 756 | if ( !v7 ) 757 | return 7; 758 | sqlite3VdbeRecordUnpack(v8, a3, a2, v7); 759 | if ( *(_WORD *)(v7 + 8) && *(_WORD *)(v7 + 8) <= *(_WORD *)(v8 + 8) ) 760 | goto LABEL_8; 761 | v6 = sqlite3CorruptError(65301); 762 | LABEL_9: 763 | if ( v7 ) 764 | sqlite3DbFree(*(_DWORD **)(*(_DWORD *)(a1 + 104) + 12), (int (__cdecl *)(int, int, int, char))v7); 765 | return v6; 766 | } 767 | ///// 768 | __cdecl ptrmapPageno(int a1, unsigned int a2) 769 | { 770 | unsigned int v3; 771 | if ( a2 <= 1 ) 772 | return 0; 773 | v3 = (a2 - 2) / (*(_DWORD *)(a1 + 40) / 5u + 1) * (*(_DWORD *)(a1 + 40) / 5u + 1) + 2; 774 | if ( v3 == (unsigned int)sqlite3PendingByte / *(_DWORD *)(a1 + 36) + 1 ) 775 | v3 = (a2 - 2) / (*(_DWORD *)(a1 + 40) / 5u + 1) * (*(_DWORD *)(a1 + 40) / 5u + 1) + 3; 776 | return v3; 777 | } 778 | ///// 779 | __cdecl ptrmapGet(int *a1, unsigned int a2, _BYTE *a3, unsigned __int32 *a4) 780 | { 781 | int result; 782 | int v5; 783 | int v6; 784 | int v7; 785 | int v8; 786 | int v9; 787 | unsigned int v10; 788 | v10 = __readgsdword(0x14u); 789 | v6 = ptrmapPageno((int)a1, a2); 790 | v7 = sqlite3PagerGet(*a1, v6, (int)&v5, 0); 791 | if ( v7 ) 792 | return v7; 793 | v8 = sqlite3PagerGetData(v5); 794 | v9 = 5 * (a2 - v6) - 5; 795 | if ( v9 >= 0 ) 796 | { 797 | *a3 = *(_BYTE *)(v9 + v8); 798 | if ( a4 ) 799 | *a4 = sqlite3Get4byte((unsigned int *)(v9 + 1 + v8)); 800 | sqlite3PagerUnref(v5); 801 | if ( *a3 && *a3 <= 5u ) 802 | result = 0; 803 | else 804 | result = sqlite3CorruptError((int)&loc_10013); 805 | } 806 | else 807 | { 808 | sqlite3PagerUnref(v5); 809 | result = sqlite3CorruptError((int)&loc_1000B); 810 | } 811 | return result; 812 | } 813 | ///// 814 | __cdecl btreeParseCellAdjustSizeForOverflow(int a1, __int16 a2, int a3) 815 | { 816 | int result; 817 | int v4; 818 | int v5; 819 | v4 = *(unsigned __int16 *)(a1 + 16); 820 | v5 = (*(_DWORD *)(a3 + 12) - v4) % (unsigned int)(*(_DWORD *)(*(_DWORD *)(a1 + 52) + 40) - 4) + v4; 821 | if ( v5 > *(unsigned __int16 *)(a1 + 14) ) 822 | *(_WORD *)(a3 + 16) = v4; 823 | else 824 | *(_WORD *)(a3 + 16) = v5; 825 | result = a3; 826 | *(_WORD *)(a3 + 18) = *(_WORD *)(a3 + 8) + *(_WORD *)(a3 + 16) - a2 + 4; 827 | return result; 828 | } 829 | ///// 830 | __cdecl btreeParseCellPtrNoPayload(int a1, int a2, int a3) 831 | { 832 | int result; 833 | *(_WORD *)(a3 + 18) = (unsigned __int8)sqlite3GetVarint((unsigned __int8 *)(a2 + 4), (_DWORD *)a3) + 4; 834 | *(_DWORD *)(a3 + 12) = 0; 835 | *(_WORD *)(a3 + 16) = 0; 836 | result = a3; 837 | *(_DWORD *)(a3 + 8) = 0; 838 | return result; 839 | } 840 | ///// 841 | __cdecl btreeParseCellPtrIndex(int a1, int a2, int a3) 842 | { 843 | int result; 844 | char *v4; 845 | char *v5; 846 | unsigned int v6; 847 | char *v7; 848 | v4 = (char *)(*(unsigned __int8 *)(a1 + 10) + a2); 849 | v6 = (unsigned __int8)*v4; 850 | if ( v6 > 0x7F ) 851 | { 852 | v7 = v4 + 8; 853 | v6 &= 0x7Fu; 854 | do 855 | v6 = (v6 << 7) | *++v4 & 0x7F; 856 | while ( *v4 < 0 && v4 < v7 ); 857 | } 858 | v5 = v4 + 1; 859 | *(_DWORD *)a3 = v6; 860 | *(_DWORD *)(a3 + 4) = 0; 861 | *(_DWORD *)(a3 + 12) = v6; 862 | *(_DWORD *)(a3 + 8) = v5; 863 | if ( v6 > *(unsigned __int16 *)(a1 + 14) ) 864 | return btreeParseCellAdjustSizeForOverflow(a1, a2, a3); 865 | *(_WORD *)(a3 + 18) = v6 + (_WORD)v5 - a2; 866 | if ( *(_WORD *)(a3 + 18) <= 3u ) 867 | *(_WORD *)(a3 + 18) = 4; 868 | result = a3; 869 | *(_WORD *)(a3 + 16) = v6; 870 | return result; 871 | } 872 | ///// 873 | __cdecl cellSizePtrNoPayload(int a1, int a2) 874 | { 875 | char *v2; 876 | unsigned int v4; 877 | v4 = a2 + 4; 878 | do 879 | v2 = (char *)v4++; 880 | while ( *v2 < 0 && v4 < a2 + 13 ); 881 | return v4 - a2; 882 | } 883 | ///// 884 | __cdecl ptrmapPutOvflPtr(int a1, int a2, unsigned int a3, int *a4) 885 | { 886 | unsigned __int32 v5; 887 | char v6[12]; 888 | unsigned int v7; 889 | unsigned __int16 v8; 890 | unsigned __int16 v9; 891 | unsigned int v10; 892 | v10 = __readgsdword(0x14u); 893 | if ( !*a4 ) 894 | { 895 | (*(void (__cdecl **)(int, unsigned int, char *))(a1 + 80))(a1, a3, v6); 896 | if ( v8 < v7 ) 897 | { 898 | if ( *(_DWORD *)(a2 + 60) < a3 || *(_DWORD *)(a2 + 60) >= v8 + a3 ) 899 | { 900 | v5 = sqlite3Get4byte((unsigned int *)(v9 - 4 + a3)); 901 | ptrmapPut(*(int **)(a1 + 52), v5, 3, *(_DWORD *)(a1 + 4), a4); 902 | } 903 | else 904 | { 905 | *a4 = sqlite3CorruptError((int)&loc_1014D); 906 | } 907 | } 908 | } 909 | return __readgsdword(0x14u) ^ v10; 910 | } 911 | ///// 912 | __cdecl decodeFlags(int a1, int a2) 913 | { 914 | void *v2; 915 | int v4; 916 | unsigned int v5; 917 | *(_BYTE *)(a1 + 8) = a2 >> 3; 918 | v5 = a2 & 0xFFFFFFF7; 919 | *(_BYTE *)(a1 + 10) = 4 * (1 - *(_BYTE *)(a1 + 8)); 920 | *(_DWORD *)(a1 + 76) = cellSizePtr; 921 | v4 = *(_DWORD *)(a1 + 52); 922 | if ( v5 == 5 ) 923 | { 924 | *(_BYTE *)(a1 + 2) = 1; 925 | if ( *(_BYTE *)(a1 + 8) ) 926 | { 927 | *(_BYTE *)(a1 + 3) = 1; 928 | v2 = btreeParseCellPtr; 929 | } 930 | else 931 | { 932 | *(_BYTE *)(a1 + 3) = 0; 933 | *(_DWORD *)(a1 + 76) = cellSizePtrNoPayload; 934 | v2 = btreeParseCellPtrNoPayload; 935 | } 936 | *(_DWORD *)(a1 + 80) = v2; 937 | *(_WORD *)(a1 + 14) = *(_WORD *)(v4 + 30); 938 | *(_WORD *)(a1 + 16) = *(_WORD *)(v4 + 32); 939 | } 940 | else 941 | { 942 | if ( v5 != 2 ) 943 | return sqlite3CorruptError((int)&loc_10325); 944 | *(_BYTE *)(a1 + 2) = 0; 945 | *(_BYTE *)(a1 + 3) = 0; 946 | *(_DWORD *)(a1 + 80) = btreeParseCellPtrIndex; 947 | *(_WORD *)(a1 + 14) = *(_WORD *)(v4 + 26); 948 | *(_WORD *)(a1 + 16) = *(_WORD *)(v4 + 28); 949 | } 950 | *(_BYTE *)(a1 + 11) = *(_BYTE *)(v4 + 21); 951 | return 0; 952 | } 953 | ///// 954 | __cdecl btreeInitPage(int a1) 955 | { 956 | int result; 957 | _DWORD *v2; 958 | unsigned __int8 *v3; 959 | v2 = *(_DWORD **)(a1 + 52); 960 | v3 = (unsigned __int8 *)(*(_DWORD *)(a1 + 56) + *(unsigned __int8 *)(a1 + 9)); 961 | if ( decodeFlags(a1, *v3) ) 962 | return sqlite3CorruptError(66491); 963 | *(_WORD *)(a1 + 26) = v2[9] - 1; 964 | *(_BYTE *)(a1 + 12) = 0; 965 | *(_WORD *)(a1 + 18) = *(unsigned __int8 *)(a1 + 9) + *(unsigned __int8 *)(a1 + 10) + 8; 966 | *(_DWORD *)(a1 + 64) = &v3[*(unsigned __int8 *)(a1 + 10) + 8]; 967 | *(_DWORD *)(a1 + 60) = v2[10] + *(_DWORD *)(a1 + 56); 968 | *(_DWORD *)(a1 + 68) = *(unsigned __int8 *)(a1 + 10) + *(_DWORD *)(a1 + 56); 969 | *(_WORD *)(a1 + 24) = _byteswap_ushort(*(_WORD *)(v3 + 3)); 970 | if ( *(unsigned __int16 *)(a1 + 24) > (v2[9] - 8) / 6u ) 971 | return sqlite3CorruptError(66505); 972 | *(_DWORD *)(a1 + 20) = -1; 973 | *(_BYTE *)a1 = 1; 974 | if ( (*(_DWORD *)(v2[1] + 28) & 0x200000) != 0 ) 975 | result = btreeCellSizeCheck(a1); 976 | else 977 | result = 0; 978 | return result; 979 | } 980 | ///// 981 | __cdecl btreePageFromDbPage(int a1, int a2, int a3) 982 | { 983 | char v3; 984 | int v5; 985 | v5 = sqlite3PagerGetExtra(a1); 986 | if ( a2 != *(_DWORD *)(v5 + 4) ) 987 | { 988 | *(_DWORD *)(v5 + 56) = sqlite3PagerGetData(a1); 989 | *(_DWORD *)(v5 + 72) = a1; 990 | *(_DWORD *)(v5 + 52) = a3; 991 | *(_DWORD *)(v5 + 4) = a2; 992 | if ( a2 == 1 ) 993 | v3 = 100; 994 | else 995 | v3 = 0; 996 | *(_BYTE *)(v5 + 9) = v3; 997 | } 998 | return v5; 999 | } 1000 | ///// 1001 | __cdecl btreePageLookup(int *a1, int a2) 1002 | { 1003 | int result; 1004 | int v3; 1005 | v3 = sqlite3PagerLookup(*a1, a2); 1006 | if ( v3 ) 1007 | result = btreePageFromDbPage(v3, a2, (int)a1); 1008 | else 1009 | result = 0; 1010 | return result; 1011 | } 1012 | ///// 1013 | __cdecl releasePageNotNull(int a1) 1014 | { 1015 | return sqlite3PagerUnrefNotNull(*(_DWORD *)(a1 + 72)); 1016 | } 1017 | ///// 1018 | __cdecl releasePage(int a1) 1019 | { 1020 | double *result; 1021 | result = &GLOBAL_OFFSET_TABLE_; 1022 | if ( a1 ) 1023 | result = releasePageNotNull(a1); 1024 | return result; 1025 | } 1026 | ///// 1027 | __cdecl pageReinit(int a1) 1028 | { 1029 | int result; 1030 | _BYTE *v2; 1031 | v2 = (_BYTE *)sqlite3PagerGetExtra(a1); 1032 | result = (unsigned __int8)*v2; 1033 | if ( (_BYTE)result ) 1034 | { 1035 | *v2 = 0; 1036 | result = sqlite3PagerPageRefcount(a1); 1037 | if ( result > 1 ) 1038 | result = btreeInitPage((int)v2); 1039 | } 1040 | return result; 1041 | } 1042 | ///// 1043 | __cdecl sqlite3BtreeSetSpillSize(int a1, int a2) 1044 | { 1045 | int *v3; 1046 | int v4; 1047 | v3 = *(int **)(a1 + 4); 1048 | sqlite3BtreeEnter(a1); 1049 | v4 = sqlite3PagerSetSpillsize(*v3, a2); 1050 | sqlite3BtreeLeave(a1); 1051 | return v4; 1052 | } 1053 | ///// 1054 | __cdecl unsetJoinExpr(double *a1, int a2) 1055 | { 1056 | double *result; 1057 | int i; 1058 | result = &GLOBAL_OFFSET_TABLE_; 1059 | while ( a1 ) 1060 | { 1061 | if ( (*((_DWORD *)a1 + 1) & 1) != 0 && (a2 < 0 || a2 == *((__int16 *)a1 + 18)) ) 1062 | *((_DWORD *)a1 + 1) &= 0xFFFFFFFE; 1063 | if ( *(_BYTE *)a1 == 0xA9 && *((_DWORD *)a1 + 5) ) 1064 | { 1065 | for ( i = 0; i < **((_DWORD **)a1 + 5); ++i ) 1066 | unsetJoinExpr(*(_DWORD *)(16 * i + *((_DWORD *)a1 + 5) + 4), a2); 1067 | } 1068 | unsetJoinExpr(*((_DWORD *)a1 + 3), a2); 1069 | result = (double *)*((_DWORD *)a1 + 4); 1070 | a1 = result; 1071 | } 1072 | return result; 1073 | } 1074 | ///// 1075 | __cdecl codeOffset(_DWORD *a1, int a2, int a3) 1076 | { 1077 | double *result; 1078 | result = &GLOBAL_OFFSET_TABLE_; 1079 | if ( a2 > 0 ) 1080 | result = (double *)sqlite3VdbeAddOp3(a1, 48, a2, a3, 1); 1081 | return result; 1082 | } 1083 | ///// 1084 | __cdecl selectInnerLoop(int *a1, int a2, int a3, _DWORD *a4, int a5, unsigned __int8 *a6, int a7, int a8) 1085 | { 1086 | int v8; 1087 | int v9; 1088 | _DWORD *v10; 1089 | int v12; 1090 | char v13; 1091 | int k; 1092 | int i; 1093 | int j; 1094 | int l; 1095 | int m; 1096 | int v19; 1097 | int v20; 1098 | int v21; 1099 | int v22; 1100 | _DWORD *v23; 1101 | int v24; 1102 | int v25; 1103 | int v26; 1104 | int v27; 1105 | _DWORD *v28; 1106 | int v29; 1107 | int v30; 1108 | char *s; 1109 | int v32; 1110 | int v33; 1111 | int v34; 1112 | int *v35; 1113 | int v36; 1114 | int v37; 1115 | int v38; 1116 | int v39; 1117 | int v40; 1118 | int v41; 1119 | int v42; 1120 | int v43; 1121 | int v44; 1122 | char v45; 1123 | unsigned int v46; 1124 | v12 = (int)a4; 1125 | v46 = __readgsdword(0x14u); 1126 | v23 = (_DWORD *)a1[2]; 1127 | v24 = *a6; 1128 | v25 = *((_DWORD *)a6 + 1); 1129 | v20 = 0; 1130 | if ( a5 ) 1131 | v8 = *(unsigned __int8 *)(a5 + 1); 1132 | else 1133 | v8 = 0; 1134 | v26 = v8; 1135 | if ( a4 && !*a4 ) 1136 | v12 = 0; 1137 | if ( !v12 && !v8 ) 1138 | codeOffset(v23, *(_DWORD *)(a2 + 12), a7); 1139 | v19 = **(_DWORD **)(a2 + 28); 1140 | if ( *((_DWORD *)a6 + 3) ) 1141 | { 1142 | if ( v19 + *((_DWORD *)a6 + 3) > a1[11] ) 1143 | a1[11] += v19; 1144 | } 1145 | else 1146 | { 1147 | if ( v12 ) 1148 | { 1149 | v20 = **(_DWORD **)v12; 1150 | if ( (*(_BYTE *)(v12 + 32) & 1) == 0 ) 1151 | ++v20; 1152 | a1[11] += v20; 1153 | } 1154 | *((_DWORD *)a6 + 3) = a1[11] + 1; 1155 | a1[11] += v19; 1156 | } 1157 | *((_DWORD *)a6 + 4) = v19; 1158 | v27 = *((_DWORD *)a6 + 3); 1159 | v21 = v27; 1160 | if ( a3 < 0 ) 1161 | { 1162 | if ( v24 != 3 ) 1163 | { 1164 | v13 = v24 == 10 || v24 == 9 || v24 == 13; 1165 | if ( v12 && !v26 && v24 != 12 && v24 != 14 ) 1166 | { 1167 | v13 |= 0xCu; 1168 | for ( i = *(_DWORD *)(v12 + 4); i < **(_DWORD **)v12; ++i ) 1169 | { 1170 | if ( *(_WORD *)(16 * i + *(_DWORD *)v12 + 16) ) 1171 | *(_WORD *)(16 * (*(unsigned __int16 *)(16 * i + *(_DWORD *)v12 + 16) - 1) + *(_DWORD *)(a2 + 28) + 16) = i - *(_WORD *)(v12 + 4) + 1; 1172 | } 1173 | v28 = *(_DWORD **)(a2 + 28); 1174 | for ( j = 0; j < *v28; ++j ) 1175 | { 1176 | if ( LOWORD(v28[4 * j + 4]) ) 1177 | { 1178 | --v19; 1179 | v21 = 0; 1180 | } 1181 | } 1182 | } 1183 | v44 = v27; 1184 | v45 = v13; 1185 | if ( *(_DWORD *)(a2 + 8) && (v13 & 8) != 0 && v20 > 0 ) 1186 | { 1187 | *(_DWORD *)(v12 + 36) = &v44; 1188 | v21 = 0; 1189 | } 1190 | else 1191 | { 1192 | innerLoopLoadRow((int)a1, a2, (int)&v44); 1193 | } 1194 | } 1195 | } 1196 | else 1197 | { 1198 | for ( k = 0; k < v19; ++k ) 1199 | sqlite3VdbeAddOp3(v23, 89, a3, k, v27 + k); 1200 | } 1201 | if ( v26 ) 1202 | { 1203 | v9 = *(unsigned __int8 *)(a5 + 1); 1204 | if ( v9 == 1 ) 1205 | { 1206 | sqlite3VdbeChangeToNoop((_DWORD **)v23, *(_DWORD *)(a5 + 8)); 1207 | } 1208 | else if ( v9 == 2 ) 1209 | { 1210 | v29 = a1[11] + 1; 1211 | a1[11] += v19; 1212 | sqlite3VdbeChangeToNoop((_DWORD **)v23, *(_DWORD *)(a5 + 8)); 1213 | v10 = sqlite3VdbeGetOp(v23, *(_DWORD *)(a5 + 8)); 1214 | *(_BYTE *)v10 = 72; 1215 | v10[1] = 1; 1216 | v10[2] = v29; 1217 | v30 = sqlite3VdbeCurrentAddr((int)v23) + v19; 1218 | for ( l = 0; l < v19; ++l ) 1219 | { 1220 | s = sqlite3ExprCollSeq(a1, *(unsigned __int8 **)(16 * l + *(_DWORD *)(a2 + 28) + 4)); 1221 | if ( l >= v19 - 1 ) 1222 | sqlite3VdbeAddOp3(v23, 53, v27 + l, a7, l + v29); 1223 | else 1224 | sqlite3VdbeAddOp3(v23, 52, v27 + l, v30, l + v29); 1225 | sqlite3VdbeChangeP4((int)v23, -1, s, -2); 1226 | sqlite3VdbeChangeP5((int)v23, 0x80u); 1227 | } 1228 | sqlite3VdbeAddOp3(v23, 77, v27, v29, v19 - 1); 1229 | } 1230 | else 1231 | { 1232 | codeDistinct((int)a1, *(_DWORD *)(a5 + 4), a7, v19, v27); 1233 | } 1234 | if ( !v12 ) 1235 | codeOffset(v23, *(_DWORD *)(a2 + 12), a7); 1236 | } 1237 | switch ( v24 ) 1238 | { 1239 | case 1: 1240 | v43 = sqlite3GetTempReg((int)a1); 1241 | sqlite3VdbeAddOp3(v23, 91, v27, v19, v43); 1242 | sqlite3VdbeAddOp4Int(v23, 130, v25, v43, v27, v19); 1243 | sqlite3ReleaseTempReg((int)a1, v43); 1244 | break; 1245 | case 2: 1246 | sqlite3VdbeAddOp3(v23, 132, v25, v27, v19); 1247 | break; 1248 | case 3: 1249 | sqlite3VdbeAddOp2(v23, 69, 1, v25); 1250 | break; 1251 | case 5: 1252 | case 6: 1253 | case 12: 1254 | case 14: 1255 | v40 = sqlite3GetTempRange(a1, v20 + 1); 1256 | sqlite3VdbeAddOp3(v23, 91, v27, v19, v40 + v20); 1257 | if ( v24 == 6 ) 1258 | { 1259 | v41 = sqlite3VdbeCurrentAddr((int)v23) + 4; 1260 | sqlite3VdbeAddOp4Int(v23, 30, v25 + 1, v41, v40, 0); 1261 | sqlite3VdbeAddOp4Int(v23, 130, v25 + 1, v40, v27, v19); 1262 | } 1263 | if ( v12 ) 1264 | { 1265 | pushOntoSorter(a1, v12, a2, v40 + v20, v21, 1, v20); 1266 | } 1267 | else 1268 | { 1269 | v42 = sqlite3GetTempReg((int)a1); 1270 | sqlite3VdbeAddOp2(v23, 120, v25, v42); 1271 | sqlite3VdbeAddOp3(v23, 121, v25, v40, v42); 1272 | sqlite3VdbeChangeP5((int)v23, 8u); 1273 | sqlite3ReleaseTempReg((int)a1, v42); 1274 | } 1275 | sqlite3ReleaseTempRange((int)a1, v40, v20 + 1); 1276 | break; 1277 | case 7: 1278 | case 8: 1279 | v22 = 0; 1280 | v35 = (int *)*((_DWORD *)a6 + 6); 1281 | v36 = *v35; 1282 | v37 = sqlite3GetTempReg((int)a1); 1283 | v38 = sqlite3GetTempRange(a1, v36 + 2); 1284 | v39 = v38 + v36 + 1; 1285 | if ( v24 == 8 ) 1286 | v22 = sqlite3VdbeAddOp4Int(v23, 30, v25 + 1, 0, v27, v19); 1287 | sqlite3VdbeAddOp3(v23, 91, v27, v19, v39); 1288 | if ( v24 == 8 ) 1289 | { 1290 | sqlite3VdbeAddOp2(v23, 130, v25 + 1, v39); 1291 | sqlite3VdbeChangeP5((int)v23, 0x10u); 1292 | } 1293 | for ( m = 0; m < v36; ++m ) 1294 | sqlite3VdbeAddOp2(v23, 78, LOWORD(v35[4 * m + 4]) + v27 - 1, m + v38); 1295 | sqlite3VdbeAddOp2(v23, 119, v25, v38 + v36); 1296 | sqlite3VdbeAddOp3(v23, 91, v38, v36 + 2, v37); 1297 | sqlite3VdbeAddOp4Int(v23, 130, v25, v37, v38, v36 + 2); 1298 | if ( v22 ) 1299 | sqlite3VdbeJumpHere(v23, v22); 1300 | sqlite3ReleaseTempReg((int)a1, v37); 1301 | sqlite3ReleaseTempRange((int)a1, v38, v36 + 2); 1302 | break; 1303 | case 9: 1304 | case 13: 1305 | if ( v12 ) 1306 | goto LABEL_80; 1307 | if ( v24 == 13 ) 1308 | sqlite3VdbeAddOp1(v23, 14, *((_DWORD *)a6 + 1)); 1309 | else 1310 | sqlite3VdbeAddOp2(v23, 80, v27, v19); 1311 | break; 1312 | case 10: 1313 | if ( v12 ) 1314 | goto LABEL_80; 1315 | break; 1316 | case 11: 1317 | if ( v12 ) 1318 | goto LABEL_80; 1319 | v34 = sqlite3GetTempReg((int)a1); 1320 | sqlite3VdbeAddOp4(v23, 91, v27, v19, v34, *((char **)a6 + 5), v19); 1321 | sqlite3VdbeAddOp4Int(v23, 130, v25, v34, v27, v19); 1322 | sqlite3ReleaseTempReg((int)a1, v34); 1323 | break; 1324 | case 15: 1325 | if ( v12 ) 1326 | { 1327 | LABEL_80: 1328 | pushOntoSorter(a1, v12, a2, v27, v21, v19, v20); 1329 | } 1330 | else 1331 | { 1332 | v32 = *((_DWORD *)a6 + 2); 1333 | v33 = sqlite3GetTempReg((int)a1); 1334 | sqlite3VdbeAddOp2(v23, 50, v27, a8); 1335 | sqlite3VdbeAddOp3(v23, 91, (v32 < 0) + v27, v19 - (v32 < 0), v33); 1336 | if ( v32 >= 0 ) 1337 | sqlite3VdbeAddOp4Int(v23, 130, v25, v33, v27, v32); 1338 | else 1339 | sqlite3VdbeAddOp3(v23, 121, v25, v33, v27); 1340 | } 1341 | break; 1342 | default: 1343 | break; 1344 | } 1345 | if ( !v12 && *(_DWORD *)(a2 + 8) ) 1346 | sqlite3VdbeAddOp2(v23, 59, *(_DWORD *)(a2 + 8), a8); 1347 | return __readgsdword(0x14u) ^ v46; 1348 | } 1349 | ///// 1350 | __cdecl sqlite3ColumnsFromExprList(int *a1, int *a2, _WORD *a3, char ***a4) 1351 | { 1352 | char *v4; 1353 | char v5; 1354 | int *v6; 1355 | unsigned int v8; 1356 | int v9; 1357 | int j; 1358 | char **v11; 1359 | char **v12; 1360 | int v13; 1361 | char *s; 1362 | int v15; 1363 | _DWORD *i; 1364 | int v17; 1365 | int v19; 1366 | unsigned int v20[6]; 1367 | v20[4] = __readgsdword(0x14u); 1368 | v18 = *a1; 1369 | sqlite3HashInit(v20); 1370 | if ( a2 ) 1371 | { 1372 | v13 = *a2; 1373 | v11 = (char **)sqlite3DbMallocZero(v18, (unsigned int)(20 * v13)); 1374 | if ( v13 > 0x7FFF ) 1375 | v13 = 0x7FFF; 1376 | } 1377 | else 1378 | { 1379 | v13 = 0; 1380 | v11 = 0; 1381 | } 1382 | *a3 = v13; 1383 | *a4 = v11; 1384 | v9 = 0; 1385 | v12 = v11; 1386 | while ( v9 < v13 && !*(_BYTE *)(v18 + 77) ) 1387 | { 1388 | s = (char *)a2[4 * v9 + 2]; 1389 | if ( !s || (a2[4 * v9 + 3] & 0x300) != 0 ) 1390 | { 1391 | for ( i = sqlite3ExprSkipCollateAndLikely((_DWORD *)a2[4 * v9 + 1]); *(_BYTE *)i == 0x8B; i = (_DWORD *)i[4] ) 1392 | ; 1393 | if ( *(_BYTE *)i == 0xA4 ) 1394 | { 1395 | v17 = *((__int16 *)i + 16); 1396 | v19 = i[11]; 1397 | if ( v17 < 0 ) 1398 | v17 = *(__int16 *)(v19 + 40); 1399 | if ( v17 < 0 ) 1400 | v4 = "rowid"; 1401 | else 1402 | v4 = *(char **)(*(_DWORD *)(v19 + 4) + 20 * v17); 1403 | s = v4; 1404 | } 1405 | else if ( *(_BYTE *)i == 59 ) 1406 | { 1407 | s = (char *)i[2]; 1408 | } 1409 | else 1410 | { 1411 | s = (char *)a2[4 * v9 + 2]; 1412 | } 1413 | } 1414 | if ( !s || sqlite3IsTrueOrFalse(s) ) 1415 | s = (char *)sqlite3MPrintf(v18, (int)"column%d", v9 + 1); 1416 | else 1417 | s = (char *)sqlite3DbStrDup(v18, s); 1418 | v8 = 0; 1419 | while ( s && sqlite3HashFind(v20, (unsigned __int8 *)s) ) 1420 | { 1421 | v15 = sqlite3Strlen30(s); 1422 | if ( v15 > 0 ) 1423 | { 1424 | for ( j = v15 - 1; j > 0 && (sqlite3CtypeMap[(_DWORD)dword_0 + (unsigned __int8)s[j]] & 4) != 0; --j ) 1425 | ; 1426 | if ( s[j] == 58 ) 1427 | v15 = j; 1428 | } 1429 | s = (char *)sqlite3MPrintf(v18, (int)"%.*z:%u", v15, s, ++v8); 1430 | if ( v8 > 3 ) 1431 | sqlite3_randomness(4, &v8); 1432 | } 1433 | *v12 = s; 1434 | v5 = sqlite3StrIHash(s); 1435 | *((_BYTE *)v12 + 15) = v5; 1436 | if ( s ) 1437 | { 1438 | v6 = sqlite3HashInsert(v20, (unsigned __int8 *)s, (int *)v12); 1439 | if ( v12 == (char **)v6 ) 1440 | sqlite3OomFault(v18); 1441 | } 1442 | ++v9; 1443 | v12 += 5; 1444 | } 1445 | sqlite3HashClear(v20); 1446 | if ( *(_BYTE *)(v18 + 77) ) 1447 | { 1448 | for ( j = 0; j < v9; ++j ) 1449 | sqlite3DbFree((_DWORD *)v18, (int (__cdecl *)(int, int, int, char))v11[5 * j]); 1450 | sqlite3DbFree((_DWORD *)v18, (int (__cdecl *)(int, int, int, char))v11); 1451 | *a4 = 0; 1452 | *a3 = 0; 1453 | return 7; 1454 | } 1455 | return 0; 1456 | } 1457 | ///// 1458 | __cdecl generateWithRecursiveQuery(int *a1, int a2, unsigned __int8 *a3) 1459 | { 1460 | int v3; 1461 | char v4; 1462 | int v5; 1463 | char v6; 1464 | int v8; 1465 | int v9; 1466 | char v10; 1467 | int i; 1468 | _DWORD *v12; 1469 | int v13; 1470 | _DWORD *v14; 1471 | int v15; 1472 | int v16; 1473 | int v17; 1474 | int v18; 1475 | int v19; 1476 | _DWORD *v20; 1477 | int v21; 1478 | int v22; 1479 | char *v23; 1480 | int v24; 1481 | int v25; 1482 | int v26; 1483 | char v27[24]; 1484 | _DWORD *v28; 1485 | unsigned int v29; 1486 | v29 = __readgsdword(0x14u); 1487 | v12 = *(_DWORD **)(a2 + 32); 1488 | v13 = **(_DWORD **)(a2 + 28); 1489 | v14 = (_DWORD *)a1[2]; 1490 | v15 = *(_DWORD *)(a2 + 52); 1491 | v8 = 0; 1492 | v9 = 0; 1493 | if ( *(_DWORD *)(a2 + 68) ) 1494 | { 1495 | sqlite3ErrorMsg((int)a1, (int)"cannot use window functions in recursive queries"); 1496 | } 1497 | else if ( !sqlite3AuthCheck((int)a1, 33, 0, 0, 0) ) 1498 | { 1499 | v16 = sqlite3VdbeMakeLabel((int)a1); 1500 | *(_WORD *)(a2 + 2) = 320; 1501 | computeLimitRegisters(a1, a2, v16); 1502 | v17 = *(_DWORD *)(a2 + 60); 1503 | v18 = *(_DWORD *)(a2 + 8); 1504 | v19 = *(_DWORD *)(a2 + 12); 1505 | *(_DWORD *)(a2 + 60) = 0; 1506 | *(_DWORD *)(a2 + 12) = 0; 1507 | *(_DWORD *)(a2 + 8) = *(_DWORD *)(a2 + 12); 1508 | v20 = *(_DWORD **)(a2 + 48); 1509 | for ( i = 0; i < *v12; ++i ) 1510 | { 1511 | if ( (v12[17 * i + 11] & 0x2000) != 0 ) 1512 | { 1513 | v8 = v12[17 * i + 12]; 1514 | break; 1515 | } 1516 | } 1517 | v3 = a1[10]; 1518 | a1[10] = v3 + 1; 1519 | v21 = v3; 1520 | if ( *(_BYTE *)a2 == 0x84 ) 1521 | { 1522 | if ( v20 ) 1523 | v4 = 8; 1524 | else 1525 | v4 = 6; 1526 | v10 = v4; 1527 | v5 = a1[10]; 1528 | a1[10] = v5 + 1; 1529 | v9 = v5; 1530 | sqlite3SelectDestInit((int)v27, v10, v21); 1531 | } 1532 | else 1533 | { 1534 | if ( v20 ) 1535 | v6 = 7; 1536 | else 1537 | v6 = 5; 1538 | sqlite3SelectDestInit((int)v27, v6, v21); 1539 | } 1540 | v22 = ++a1[11]; 1541 | sqlite3VdbeAddOp3(v14, 114, v8, v22, v13); 1542 | if ( v20 ) 1543 | { 1544 | v23 = (char *)multiSelectOrderByKeyInfo(a1, a2, 1); 1545 | sqlite3VdbeAddOp4(v14, 100, v21, *v20 + 2, 0, v23, -9); 1546 | v28 = v20; 1547 | } 1548 | else 1549 | { 1550 | sqlite3VdbeAddOp2(v14, 100, v21, v13); 1551 | } 1552 | if ( v9 ) 1553 | { 1554 | *(_DWORD *)(a2 + 20) = sqlite3VdbeAddOp2(v14, 100, v9, 0); 1555 | *(_DWORD *)(a2 + 4) |= 0x20u; 1556 | } 1557 | *(_DWORD *)(a2 + 48) = 0; 1558 | *(_DWORD *)(v15 + 56) = 0; 1559 | sqlite3VdbeExplain(a1, 1, (int)"SETUP"); 1560 | v24 = sqlite3Select(a1, v15, v27); 1561 | *(_DWORD *)(v15 + 56) = a2; 1562 | if ( !v24 ) 1563 | { 1564 | v25 = sqlite3VdbeAddOp2(v14, 37, v21, v16); 1565 | sqlite3VdbeAddOp1(v14, 128, v8); 1566 | if ( v20 ) 1567 | sqlite3VdbeAddOp3(v14, 89, v21, *v20 + 1, v22); 1568 | else 1569 | sqlite3VdbeAddOp2(v14, 126, v21, v22); 1570 | sqlite3VdbeAddOp1(v14, 122, v21); 1571 | v26 = sqlite3VdbeMakeLabel((int)a1); 1572 | codeOffset(v14, v19, v26); 1573 | selectInnerLoop(a1, a2, v8, 0, 0, a3, v26, v16); 1574 | if ( v18 ) 1575 | sqlite3VdbeAddOp2(v14, 59, v18, v16); 1576 | sqlite3VdbeResolveLabel((int)v14, v26); 1577 | if ( (*(_DWORD *)(a2 + 4) & 8) != 0 ) 1578 | { 1579 | sqlite3ErrorMsg((int)a1, (int)"recursive aggregate queries not supported"); 1580 | } 1581 | else 1582 | { 1583 | *(_DWORD *)(a2 + 52) = 0; 1584 | sqlite3VdbeExplain(a1, 1, (int)"RECURSIVE STEP"); 1585 | sqlite3Select(a1, a2, v27); 1586 | *(_DWORD *)(a2 + 52) = v15; 1587 | } 1588 | sqlite3VdbeGoto(v14, v25); 1589 | sqlite3VdbeResolveLabel((int)v14, v16); 1590 | } 1591 | sqlite3ExprListDelete((_DWORD *)*a1, *(int (__cdecl **)(int, int, int, char))(a2 + 48)); 1592 | *(_DWORD *)(a2 + 48) = v20; 1593 | *(_DWORD *)(a2 + 60) = v17; 1594 | } 1595 | return __readgsdword(0x14u) ^ v29; 1596 | } 1597 | ///// 1598 | __cdecl multiSelect(int *a1, unsigned __int8 *a2, int a3) 1599 | { 1600 | const char *v3; 1601 | const char *v4; 1602 | int v6; 1603 | __int16 v7; 1604 | int v8; 1605 | int v9; 1606 | const char *v10; 1607 | int v11; 1608 | int v12; 1609 | int v13; 1610 | int v14; 1611 | const char *v15; 1612 | char *v16; 1613 | char v17; 1614 | int v18; 1615 | double *v19; 1616 | int v20; 1617 | int v21; 1618 | int v22; 1619 | int j; 1620 | unsigned __int8 *i; 1621 | char **v25; 1622 | int v26; 1623 | int v27; 1624 | int *v28; 1625 | int v29; 1626 | int v30; 1627 | int v31; 1628 | int v32; 1629 | int v33; 1630 | int v34; 1631 | int v35; 1632 | int v36; 1633 | int v37; 1634 | int v38; 1635 | int v39; 1636 | int v40; 1637 | _DWORD *v41; 1638 | int v42; 1639 | int v43; 1640 | int v44; 1641 | int v45; 1642 | int v46; 1643 | int v47; 1644 | int v48; 1645 | int v49; 1646 | int v50[9]; 1647 | v50[7] = __readgsdword(0x14u); 1648 | v18 = 0; 1649 | v19 = 0; 1650 | v26 = *a1; 1651 | v27 = *((_DWORD *)a2 + 13); 1652 | v43 = *(_DWORD *)a3; 1653 | v44 = *(_DWORD *)(a3 + 4); 1654 | v45 = *(_DWORD *)(a3 + 8); 1655 | v46 = *(_DWORD *)(a3 + 12); 1656 | v47 = *(_DWORD *)(a3 + 16); 1657 | v48 = *(_DWORD *)(a3 + 20); 1658 | v49 = *(_DWORD *)(a3 + 24); 1659 | if ( *(_DWORD *)(v27 + 48) || *(_DWORD *)(v27 + 60) ) 1660 | { 1661 | v3 = selectOpName(*a2); 1662 | if ( *(_DWORD *)(v27 + 48) ) 1663 | v4 = "ORDER BY"; 1664 | else 1665 | v4 = "LIMIT"; 1666 | sqlite3ErrorMsg((int)a1, (int)"%s clause should come after %s not before", v4, v3); 1667 | v18 = 1; 1668 | goto LABEL_69; 1669 | } 1670 | v28 = sqlite3GetVdbe(a1); 1671 | if ( (_BYTE)v43 == 12 ) 1672 | { 1673 | sqlite3VdbeAddOp2(v28, 100, v44, **((_DWORD **)a2 + 7)); 1674 | LOBYTE(v43) = 14; 1675 | } 1676 | if ( (*((_DWORD *)a2 + 1) & 0x400) != 0 ) 1677 | { 1678 | v18 = multiSelectValues(a1, (int)a2, (unsigned __int8 *)&v43); 1679 | if ( v18 >= 0 ) 1680 | goto LABEL_69; 1681 | v18 = 0; 1682 | } 1683 | if ( (*((_DWORD *)a2 + 1) & 0x2000) != 0 ) 1684 | { 1685 | generateWithRecursiveQuery(a1, (int)a2, (unsigned __int8 *)&v43); 1686 | goto LABEL_52; 1687 | } 1688 | if ( *((_DWORD *)a2 + 12) ) 1689 | return multiSelectOrderBy(a1, a2, (unsigned __int8 *)a3); 1690 | if ( !*(_DWORD *)(v27 + 52) ) 1691 | { 1692 | sqlite3VdbeExplain(a1, 1, (int)"COMPOUND QUERY"); 1693 | sqlite3VdbeExplain(a1, 1, (int)"LEFT-MOST SUBQUERY"); 1694 | } 1695 | v6 = *a2; 1696 | if ( v6 == 133 ) 1697 | { 1698 | v20 = 0; 1699 | *(_DWORD *)(v27 + 8) = *((_DWORD *)a2 + 2); 1700 | *(_DWORD *)(v27 + 12) = *((_DWORD *)a2 + 3); 1701 | *(_DWORD *)(v27 + 60) = *((_DWORD *)a2 + 15); 1702 | v18 = sqlite3Select(a1, v27, &v43); 1703 | *((_DWORD *)a2 + 15) = 0; 1704 | if ( !v18 ) 1705 | { 1706 | *((_DWORD *)a2 + 13) = 0; 1707 | *((_DWORD *)a2 + 2) = *(_DWORD *)(v27 + 8); 1708 | *((_DWORD *)a2 + 3) = *(_DWORD *)(v27 + 12); 1709 | if ( *((_DWORD *)a2 + 2) ) 1710 | { 1711 | v20 = sqlite3VdbeAddOp1(v28, 20, *((_DWORD *)a2 + 2)); 1712 | if ( *((_DWORD *)a2 + 3) ) 1713 | sqlite3VdbeAddOp3(v28, 152, *((_DWORD *)a2 + 2), *((_DWORD *)a2 + 3) + 1, *((_DWORD *)a2 + 3)); 1714 | } 1715 | sqlite3VdbeExplain(a1, 1, (int)"UNION ALL"); 1716 | v18 = sqlite3Select(a1, a2, &v43); 1717 | v19 = (double *)*((_DWORD *)a2 + 13); 1718 | *((_DWORD *)a2 + 13) = v27; 1719 | *((_WORD *)a2 + 1) = sqlite3LogEstAdd(*((_WORD *)a2 + 1), *(_WORD *)(v27 + 2)); 1720 | if ( *(_DWORD *)(v27 + 60) ) 1721 | { 1722 | if ( sqlite3ExprIsInteger(*(_DWORD **)(*(_DWORD *)(v27 + 60) + 12), v50) ) 1723 | { 1724 | if ( v50[0] > 0 ) 1725 | { 1726 | v7 = *((_WORD *)a2 + 1); 1727 | if ( v7 > (__int16)sqlite3LogEst(v50[0]) ) 1728 | *((_WORD *)a2 + 1) = sqlite3LogEst(v50[0]); 1729 | } 1730 | } 1731 | } 1732 | if ( v20 ) 1733 | sqlite3VdbeJumpHere(v28, v20); 1734 | goto LABEL_50; 1735 | } 1736 | } 1737 | else 1738 | { 1739 | if ( v6 == 134 || v6 == 132 ) 1740 | { 1741 | if ( (unsigned __int8)v43 == 1 ) 1742 | { 1743 | v21 = v44; 1744 | sqlite3SelectDestInit((int)v50, 1, v44); 1745 | } 1746 | else 1747 | { 1748 | v8 = a1[10]; 1749 | a1[10] = v8 + 1; 1750 | v21 = v8; 1751 | *((_DWORD *)a2 + 5) = sqlite3VdbeAddOp2(v28, 100, v8, 0); 1752 | v9 = findRightmost((int)a2); 1753 | *(_DWORD *)(v9 + 4) |= 0x20u; 1754 | sqlite3SelectDestInit((int)v50, 1, v21); 1755 | } 1756 | v18 = sqlite3Select(a1, v27, v50); 1757 | if ( v18 ) 1758 | goto LABEL_69; 1759 | if ( *a2 == 0x86 ) 1760 | v17 = 2; 1761 | else 1762 | v17 = 1; 1763 | *((_DWORD *)a2 + 13) = 0; 1764 | v29 = *((_DWORD *)a2 + 15); 1765 | *((_DWORD *)a2 + 15) = 0; 1766 | LOBYTE(v50[0]) = v17; 1767 | v10 = selectOpName(*a2); 1768 | sqlite3VdbeExplain(a1, 1, (int)"%s USING TEMP B-TREE", v10); 1769 | v18 = sqlite3Select(a1, a2, v50); 1770 | v19 = (double *)*((_DWORD *)a2 + 13); 1771 | *((_DWORD *)a2 + 13) = v27; 1772 | *((_DWORD *)a2 + 12) = 0; 1773 | if ( *a2 == 0x84 ) 1774 | *((_WORD *)a2 + 1) = sqlite3LogEstAdd(*((_WORD *)a2 + 1), *(_WORD *)(v27 + 2)); 1775 | sqlite3ExprDelete((_DWORD *)v26, *((_DWORD *)a2 + 15)); 1776 | *((_DWORD *)a2 + 15) = v29; 1777 | *((_DWORD *)a2 + 2) = 0; 1778 | *((_DWORD *)a2 + 3) = 0; 1779 | if ( (unsigned __int8)v43 != 1 && !*(_BYTE *)(v26 + 77) ) 1780 | { 1781 | v30 = sqlite3VdbeMakeLabel((int)a1); 1782 | v31 = sqlite3VdbeMakeLabel((int)a1); 1783 | computeLimitRegisters(a1, (int)a2, v30); 1784 | sqlite3VdbeAddOp2(v28, 37, v21, v30); 1785 | v32 = sqlite3VdbeCurrentAddr((int)v28); 1786 | selectInnerLoop(a1, (int)a2, v21, 0, 0, (unsigned __int8 *)&v43, v31, v30); 1787 | sqlite3VdbeResolveLabel((int)v28, v31); 1788 | sqlite3VdbeAddOp2(v28, 5, v21, v32); 1789 | sqlite3VdbeResolveLabel((int)v28, v30); 1790 | sqlite3VdbeAddOp2(v28, 116, v21, 0); 1791 | } 1792 | goto LABEL_50; 1793 | } 1794 | v11 = a1[10]; 1795 | a1[10] = v11 + 1; 1796 | v33 = v11; 1797 | v12 = a1[10]; 1798 | a1[10] = v12 + 1; 1799 | v34 = v12; 1800 | *((_DWORD *)a2 + 5) = sqlite3VdbeAddOp2(v28, 100, v33, 0); 1801 | v13 = findRightmost((int)a2); 1802 | *(_DWORD *)(v13 + 4) |= 0x20u; 1803 | sqlite3SelectDestInit((int)v50, 1, v33); 1804 | v14 = sqlite3Select(a1, v27, v50); 1805 | v18 = v14; 1806 | if ( !v14 ) 1807 | { 1808 | *((_DWORD *)a2 + 6) = sqlite3VdbeAddOp2(v28, 100, v34, 0); 1809 | *((_DWORD *)a2 + 13) = 0; 1810 | v35 = *((_DWORD *)a2 + 15); 1811 | *((_DWORD *)a2 + 15) = 0; 1812 | v50[1] = v34; 1813 | v15 = selectOpName(*a2); 1814 | sqlite3VdbeExplain(a1, 1, (int)"%s USING TEMP B-TREE", v15); 1815 | v18 = sqlite3Select(a1, a2, v50); 1816 | v19 = (double *)*((_DWORD *)a2 + 13); 1817 | *((_DWORD *)a2 + 13) = v27; 1818 | if ( *((_WORD *)a2 + 1) > *(_WORD *)(v27 + 2) ) 1819 | *((_WORD *)a2 + 1) = *(_WORD *)(v27 + 2); 1820 | sqlite3ExprDelete((_DWORD *)v26, *((_DWORD *)a2 + 15)); 1821 | *((_DWORD *)a2 + 15) = v35; 1822 | if ( !v18 ) 1823 | { 1824 | v36 = sqlite3VdbeMakeLabel((int)a1); 1825 | v37 = sqlite3VdbeMakeLabel((int)a1); 1826 | computeLimitRegisters(a1, (int)a2, v36); 1827 | sqlite3VdbeAddOp2(v28, 37, v33, v36); 1828 | v38 = sqlite3GetTempReg((int)a1); 1829 | v39 = sqlite3VdbeAddOp2(v28, 126, v33, v38); 1830 | sqlite3VdbeAddOp4Int(v28, 29, v34, v37, v38, 0); 1831 | sqlite3ReleaseTempReg((int)a1, v38); 1832 | selectInnerLoop(a1, (int)a2, v33, 0, 0, (unsigned __int8 *)&v43, v37, v36); 1833 | sqlite3VdbeResolveLabel((int)v28, v37); 1834 | sqlite3VdbeAddOp2(v28, 5, v33, v39); 1835 | sqlite3VdbeResolveLabel((int)v28, v36); 1836 | sqlite3VdbeAddOp2(v28, 116, v34, 0); 1837 | sqlite3VdbeAddOp2(v28, 116, v33, 0); 1838 | } 1839 | } 1840 | } 1841 | LABEL_50: 1842 | if ( !*((_DWORD *)a2 + 14) ) 1843 | sqlite3VdbeExplainPop((int)a1); 1844 | LABEL_52: 1845 | if ( !a1[9] && (*((_DWORD *)a2 + 1) & 0x20) != 0 ) 1846 | { 1847 | v40 = **((_DWORD **)a2 + 7); 1848 | v41 = (_DWORD *)sqlite3KeyInfoAlloc(v26, v40, 1); 1849 | if ( v41 ) 1850 | { 1851 | v22 = 0; 1852 | v25 = (char **)(v41 + 5); 1853 | while ( v22 < v40 ) 1854 | { 1855 | *v25 = multiSelectCollSeq(a1, (int)a2, v22); 1856 | if ( !*v25 ) 1857 | *v25 = *(char **)(v26 + 8); 1858 | ++v22; 1859 | ++v25; 1860 | } 1861 | for ( i = a2; i; i = (unsigned __int8 *)*((_DWORD *)i + 13) ) 1862 | { 1863 | for ( j = 0; j <= 1; ++j ) 1864 | { 1865 | v42 = *(_DWORD *)&i[4 * j + 20]; 1866 | if ( v42 < 0 ) 1867 | break; 1868 | sqlite3VdbeChangeP2(v28, v42, v40); 1869 | v16 = (char *)sqlite3KeyInfoRef(v41); 1870 | sqlite3VdbeChangeP4((int)v28, v42, v16, -9); 1871 | *(_DWORD *)&i[4 * j + 20] = -1; 1872 | } 1873 | } 1874 | sqlite3KeyInfoUnref((int)v41); 1875 | } 1876 | else 1877 | { 1878 | v18 = 7; 1879 | } 1880 | } 1881 | LABEL_69: 1882 | *(_DWORD *)(a3 + 12) = v46; 1883 | *(_DWORD *)(a3 + 16) = v47; 1884 | sqlite3SelectDelete((_DWORD *)v26, v19); 1885 | return v18; 1886 | } --------------------------------------------------------------------------------