├── 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 |
4 |
5 | |
6 |
7 | FidelityGPT: Correcting Decompilation Distortions with Retrieval Augmented Generation
8 | |
9 |
10 |
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 | }
--------------------------------------------------------------------------------