angr 9.2.192__cp311-cp311-macosx_10_12_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- angr/__init__.py +366 -0
- angr/__main__.py +182 -0
- angr/ail_callable.py +79 -0
- angr/ailment/__init__.py +83 -0
- angr/ailment/block.py +88 -0
- angr/ailment/block_walker.py +856 -0
- angr/ailment/constant.py +3 -0
- angr/ailment/converter_common.py +11 -0
- angr/ailment/converter_pcode.py +648 -0
- angr/ailment/converter_vex.py +829 -0
- angr/ailment/expression.py +1655 -0
- angr/ailment/manager.py +34 -0
- angr/ailment/statement.py +973 -0
- angr/ailment/tagged_object.py +58 -0
- angr/ailment/utils.py +114 -0
- angr/analyses/__init__.py +117 -0
- angr/analyses/analysis.py +429 -0
- angr/analyses/backward_slice.py +686 -0
- angr/analyses/binary_optimizer.py +670 -0
- angr/analyses/bindiff.py +1512 -0
- angr/analyses/boyscout.py +76 -0
- angr/analyses/callee_cleanup_finder.py +74 -0
- angr/analyses/calling_convention/__init__.py +6 -0
- angr/analyses/calling_convention/calling_convention.py +1113 -0
- angr/analyses/calling_convention/fact_collector.py +647 -0
- angr/analyses/calling_convention/utils.py +60 -0
- angr/analyses/cdg.py +189 -0
- angr/analyses/cfg/__init__.py +23 -0
- angr/analyses/cfg/cfb.py +451 -0
- angr/analyses/cfg/cfg.py +74 -0
- angr/analyses/cfg/cfg_arch_options.py +95 -0
- angr/analyses/cfg/cfg_base.py +2954 -0
- angr/analyses/cfg/cfg_emulated.py +3451 -0
- angr/analyses/cfg/cfg_fast.py +5431 -0
- angr/analyses/cfg/cfg_fast_soot.py +662 -0
- angr/analyses/cfg/cfg_job_base.py +203 -0
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +30 -0
- angr/analyses/cfg/indirect_jump_resolvers/aarch64_macho_got.py +77 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
- angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +159 -0
- angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +339 -0
- angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +82 -0
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2490 -0
- angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
- angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
- angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
- angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
- angr/analyses/cfg_slice_to_sink/graph.py +87 -0
- angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
- angr/analyses/class_identifier.py +63 -0
- angr/analyses/code_tagging.py +123 -0
- angr/analyses/codecave.py +77 -0
- angr/analyses/complete_calling_conventions.py +475 -0
- angr/analyses/congruency_check.py +377 -0
- angr/analyses/data_dep/__init__.py +16 -0
- angr/analyses/data_dep/data_dependency_analysis.py +595 -0
- angr/analyses/data_dep/dep_nodes.py +171 -0
- angr/analyses/data_dep/sim_act_location.py +49 -0
- angr/analyses/datagraph_meta.py +105 -0
- angr/analyses/ddg.py +1670 -0
- angr/analyses/decompiler/__init__.py +41 -0
- angr/analyses/decompiler/ail_simplifier.py +2246 -0
- angr/analyses/decompiler/ailgraph_walker.py +49 -0
- angr/analyses/decompiler/block_io_finder.py +302 -0
- angr/analyses/decompiler/block_similarity.py +199 -0
- angr/analyses/decompiler/block_simplifier.py +397 -0
- angr/analyses/decompiler/callsite_maker.py +579 -0
- angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +618 -0
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +24 -0
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +354 -0
- angr/analyses/decompiler/clinic.py +3662 -0
- angr/analyses/decompiler/condition_processor.py +1323 -0
- angr/analyses/decompiler/counters/__init__.py +16 -0
- angr/analyses/decompiler/counters/boolean_counter.py +27 -0
- angr/analyses/decompiler/counters/call_counter.py +77 -0
- angr/analyses/decompiler/counters/expression_counters.py +77 -0
- angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
- angr/analyses/decompiler/decompilation_cache.py +54 -0
- angr/analyses/decompiler/decompilation_options.py +317 -0
- angr/analyses/decompiler/decompiler.py +796 -0
- angr/analyses/decompiler/dephication/__init__.py +6 -0
- angr/analyses/decompiler/dephication/dephication_base.py +100 -0
- angr/analyses/decompiler/dephication/graph_dephication.py +70 -0
- angr/analyses/decompiler/dephication/graph_rewriting.py +112 -0
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +357 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +528 -0
- angr/analyses/decompiler/dephication/seqnode_dephication.py +156 -0
- angr/analyses/decompiler/dirty_rewriters/__init__.py +7 -0
- angr/analyses/decompiler/dirty_rewriters/amd64_dirty.py +74 -0
- angr/analyses/decompiler/dirty_rewriters/rewriter_base.py +27 -0
- angr/analyses/decompiler/empty_node_remover.py +212 -0
- angr/analyses/decompiler/expression_narrower.py +290 -0
- angr/analyses/decompiler/goto_manager.py +112 -0
- angr/analyses/decompiler/graph_region.py +441 -0
- angr/analyses/decompiler/jump_target_collector.py +37 -0
- angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
- angr/analyses/decompiler/label_collector.py +32 -0
- angr/analyses/decompiler/node_replacer.py +42 -0
- angr/analyses/decompiler/notes/__init__.py +9 -0
- angr/analyses/decompiler/notes/decompilation_note.py +48 -0
- angr/analyses/decompiler/notes/deobfuscated_strings.py +56 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +164 -0
- angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
- angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
- angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +211 -0
- angr/analyses/decompiler/optimization_passes/const_derefs.py +127 -0
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
- angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1221 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +236 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_eval.py +186 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +502 -0
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +138 -0
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +618 -0
- angr/analyses/decompiler/optimization_passes/inlined_strlen_simplifier.py +274 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +337 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +939 -0
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +710 -0
- angr/analyses/decompiler/optimization_passes/peephole_simplifier.py +75 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +263 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier_adv.py +198 -0
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +632 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +166 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
- angr/analyses/decompiler/optimization_passes/static_vvar_rewriter.py +336 -0
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +166 -0
- angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
- angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +477 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
- angr/analyses/decompiler/peephole_optimizations/__init__.py +136 -0
- angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
- angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
- angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
- angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
- angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +182 -0
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
- angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +436 -0
- angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memcpy.py +78 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memset.py +262 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +217 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +106 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy.py +256 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy_consolidation.py +296 -0
- angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
- angr/analyses/decompiler/peephole_optimizations/modulo_simplifier.py +89 -0
- angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
- angr/analyses/decompiler/peephole_optimizations/optimized_div_simplifier.py +356 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
- angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +125 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +273 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_derefs.py +21 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +115 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
- angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +143 -0
- angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
- angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
- angr/analyses/decompiler/presets/__init__.py +22 -0
- angr/analyses/decompiler/presets/basic.py +36 -0
- angr/analyses/decompiler/presets/fast.py +66 -0
- angr/analyses/decompiler/presets/full.py +76 -0
- angr/analyses/decompiler/presets/malware.py +70 -0
- angr/analyses/decompiler/presets/preset.py +37 -0
- angr/analyses/decompiler/redundant_label_remover.py +141 -0
- angr/analyses/decompiler/region_identifier.py +1319 -0
- angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
- angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +838 -0
- angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
- angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
- angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
- angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +270 -0
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
- angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
- angr/analyses/decompiler/region_walker.py +24 -0
- angr/analyses/decompiler/return_maker.py +72 -0
- angr/analyses/decompiler/semantic_naming/__init__.py +37 -0
- angr/analyses/decompiler/semantic_naming/array_index_naming.py +196 -0
- angr/analyses/decompiler/semantic_naming/boolean_naming.py +264 -0
- angr/analyses/decompiler/semantic_naming/call_result_naming.py +220 -0
- angr/analyses/decompiler/semantic_naming/naming_base.py +166 -0
- angr/analyses/decompiler/semantic_naming/orchestrator.py +107 -0
- angr/analyses/decompiler/semantic_naming/pointer_naming.py +334 -0
- angr/analyses/decompiler/semantic_naming/region_loop_counter_naming.py +246 -0
- angr/analyses/decompiler/semantic_naming/size_naming.py +137 -0
- angr/analyses/decompiler/seq_to_blocks.py +20 -0
- angr/analyses/decompiler/sequence_walker.py +261 -0
- angr/analyses/decompiler/ssailification/__init__.py +4 -0
- angr/analyses/decompiler/ssailification/rewriting.py +451 -0
- angr/analyses/decompiler/ssailification/rewriting_engine.py +1091 -0
- angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
- angr/analyses/decompiler/ssailification/ssailification.py +283 -0
- angr/analyses/decompiler/ssailification/traversal.py +127 -0
- angr/analyses/decompiler/ssailification/traversal_engine.py +323 -0
- angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
- angr/analyses/decompiler/stack_item.py +36 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
- angr/analyses/decompiler/structured_codegen/base.py +193 -0
- angr/analyses/decompiler/structured_codegen/c.py +4257 -0
- angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
- angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
- angr/analyses/decompiler/structuring/__init__.py +30 -0
- angr/analyses/decompiler/structuring/dream.py +1217 -0
- angr/analyses/decompiler/structuring/phoenix.py +3636 -0
- angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
- angr/analyses/decompiler/structuring/sailr.py +120 -0
- angr/analyses/decompiler/structuring/structurer_base.py +1140 -0
- angr/analyses/decompiler/structuring/structurer_nodes.py +442 -0
- angr/analyses/decompiler/utils.py +1224 -0
- angr/analyses/deobfuscator/__init__.py +23 -0
- angr/analyses/deobfuscator/api_obf_finder.py +333 -0
- angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +80 -0
- angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
- angr/analyses/deobfuscator/data_transformation_embedder.py +633 -0
- angr/analyses/deobfuscator/hash_lookup_api_deobfuscator.py +156 -0
- angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
- angr/analyses/deobfuscator/scope_ops_analyzer.py +68 -0
- angr/analyses/deobfuscator/string_obf_finder.py +983 -0
- angr/analyses/deobfuscator/string_obf_opt_passes.py +136 -0
- angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
- angr/analyses/disassembly.py +1351 -0
- angr/analyses/disassembly_utils.py +101 -0
- angr/analyses/dominance_frontier.py +57 -0
- angr/analyses/fcp/__init__.py +4 -0
- angr/analyses/fcp/fcp.py +427 -0
- angr/analyses/find_objects_static.py +205 -0
- angr/analyses/flirt/__init__.py +47 -0
- angr/analyses/flirt/consts.py +160 -0
- angr/analyses/flirt/flirt.py +249 -0
- angr/analyses/flirt/flirt_function.py +20 -0
- angr/analyses/flirt/flirt_matcher.py +352 -0
- angr/analyses/flirt/flirt_module.py +32 -0
- angr/analyses/flirt/flirt_node.py +23 -0
- angr/analyses/flirt/flirt_sig.py +359 -0
- angr/analyses/flirt/flirt_utils.py +31 -0
- angr/analyses/forward_analysis/__init__.py +12 -0
- angr/analyses/forward_analysis/forward_analysis.py +619 -0
- angr/analyses/forward_analysis/job_info.py +64 -0
- angr/analyses/forward_analysis/visitors/__init__.py +14 -0
- angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
- angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
- angr/analyses/forward_analysis/visitors/graph.py +242 -0
- angr/analyses/forward_analysis/visitors/loop.py +29 -0
- angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
- angr/analyses/identifier/__init__.py +5 -0
- angr/analyses/identifier/custom_callable.py +137 -0
- angr/analyses/identifier/errors.py +10 -0
- angr/analyses/identifier/func.py +60 -0
- angr/analyses/identifier/functions/__init__.py +37 -0
- angr/analyses/identifier/functions/atoi.py +73 -0
- angr/analyses/identifier/functions/based_atoi.py +125 -0
- angr/analyses/identifier/functions/fdprintf.py +123 -0
- angr/analyses/identifier/functions/free.py +64 -0
- angr/analyses/identifier/functions/int2str.py +287 -0
- angr/analyses/identifier/functions/malloc.py +111 -0
- angr/analyses/identifier/functions/memcmp.py +67 -0
- angr/analyses/identifier/functions/memcpy.py +89 -0
- angr/analyses/identifier/functions/memset.py +43 -0
- angr/analyses/identifier/functions/printf.py +123 -0
- angr/analyses/identifier/functions/recv_until.py +312 -0
- angr/analyses/identifier/functions/skip_calloc.py +73 -0
- angr/analyses/identifier/functions/skip_realloc.py +97 -0
- angr/analyses/identifier/functions/skip_recv_n.py +105 -0
- angr/analyses/identifier/functions/snprintf.py +112 -0
- angr/analyses/identifier/functions/sprintf.py +116 -0
- angr/analyses/identifier/functions/strcasecmp.py +33 -0
- angr/analyses/identifier/functions/strcmp.py +113 -0
- angr/analyses/identifier/functions/strcpy.py +43 -0
- angr/analyses/identifier/functions/strlen.py +27 -0
- angr/analyses/identifier/functions/strncmp.py +104 -0
- angr/analyses/identifier/functions/strncpy.py +65 -0
- angr/analyses/identifier/functions/strtol.py +89 -0
- angr/analyses/identifier/identify.py +825 -0
- angr/analyses/identifier/runner.py +360 -0
- angr/analyses/init_finder.py +289 -0
- angr/analyses/loop_analysis/__init__.py +4 -0
- angr/analyses/loop_analysis/loop_analysis.py +464 -0
- angr/analyses/loop_analysis.py +349 -0
- angr/analyses/loop_unroller/__init__.py +4 -0
- angr/analyses/loop_unroller/loop_unroller.py +222 -0
- angr/analyses/loopfinder.py +171 -0
- angr/analyses/outliner/__init__.py +7 -0
- angr/analyses/outliner/outliner.py +402 -0
- angr/analyses/patchfinder.py +137 -0
- angr/analyses/pathfinder.py +282 -0
- angr/analyses/propagator/__init__.py +5 -0
- angr/analyses/propagator/engine_base.py +62 -0
- angr/analyses/propagator/engine_vex.py +297 -0
- angr/analyses/propagator/propagator.py +361 -0
- angr/analyses/propagator/top_checker_mixin.py +218 -0
- angr/analyses/propagator/values.py +117 -0
- angr/analyses/propagator/vex_vars.py +68 -0
- angr/analyses/proximity_graph.py +444 -0
- angr/analyses/purity/__init__.py +15 -0
- angr/analyses/purity/analysis.py +78 -0
- angr/analyses/purity/engine.py +593 -0
- angr/analyses/reaching_definitions/__init__.py +67 -0
- angr/analyses/reaching_definitions/call_trace.py +73 -0
- angr/analyses/reaching_definitions/dep_graph.py +433 -0
- angr/analyses/reaching_definitions/engine_ail.py +1128 -0
- angr/analyses/reaching_definitions/engine_vex.py +1128 -0
- angr/analyses/reaching_definitions/external_codeloc.py +0 -0
- angr/analyses/reaching_definitions/function_handler.py +639 -0
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
- angr/analyses/reaching_definitions/function_handler_library/stdio.py +269 -0
- angr/analyses/reaching_definitions/function_handler_library/stdlib.py +195 -0
- angr/analyses/reaching_definitions/function_handler_library/string.py +158 -0
- angr/analyses/reaching_definitions/function_handler_library/unistd.py +51 -0
- angr/analyses/reaching_definitions/heap_allocator.py +70 -0
- angr/analyses/reaching_definitions/rd_initializer.py +237 -0
- angr/analyses/reaching_definitions/rd_state.py +579 -0
- angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
- angr/analyses/reaching_definitions/subject.py +65 -0
- angr/analyses/reassembler.py +2900 -0
- angr/analyses/s_liveness.py +254 -0
- angr/analyses/s_propagator.py +575 -0
- angr/analyses/s_reaching_definitions/__init__.py +12 -0
- angr/analyses/s_reaching_definitions/s_rda_model.py +145 -0
- angr/analyses/s_reaching_definitions/s_rda_view.py +344 -0
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +230 -0
- angr/analyses/smc.py +160 -0
- angr/analyses/soot_class_hierarchy.py +273 -0
- angr/analyses/stack_pointer_tracker.py +954 -0
- angr/analyses/static_hooker.py +53 -0
- angr/analyses/typehoon/__init__.py +5 -0
- angr/analyses/typehoon/dfa.py +118 -0
- angr/analyses/typehoon/lifter.py +133 -0
- angr/analyses/typehoon/simple_solver.py +2009 -0
- angr/analyses/typehoon/translator.py +283 -0
- angr/analyses/typehoon/typeconsts.py +439 -0
- angr/analyses/typehoon/typehoon.py +338 -0
- angr/analyses/typehoon/typevars.py +633 -0
- angr/analyses/typehoon/variance.py +11 -0
- angr/analyses/unpacker/__init__.py +6 -0
- angr/analyses/unpacker/obfuscation_detector.py +103 -0
- angr/analyses/unpacker/packing_detector.py +138 -0
- angr/analyses/variable_recovery/__init__.py +9 -0
- angr/analyses/variable_recovery/annotations.py +58 -0
- angr/analyses/variable_recovery/engine_ail.py +978 -0
- angr/analyses/variable_recovery/engine_base.py +1256 -0
- angr/analyses/variable_recovery/engine_vex.py +594 -0
- angr/analyses/variable_recovery/irsb_scanner.py +143 -0
- angr/analyses/variable_recovery/variable_recovery.py +574 -0
- angr/analyses/variable_recovery/variable_recovery_base.py +489 -0
- angr/analyses/variable_recovery/variable_recovery_fast.py +669 -0
- angr/analyses/veritesting.py +626 -0
- angr/analyses/vfg.py +1898 -0
- angr/analyses/vsa_ddg.py +420 -0
- angr/analyses/vtable.py +92 -0
- angr/analyses/xrefs.py +286 -0
- angr/angrdb/__init__.py +14 -0
- angr/angrdb/db.py +215 -0
- angr/angrdb/models.py +184 -0
- angr/angrdb/serializers/__init__.py +10 -0
- angr/angrdb/serializers/cfg_model.py +41 -0
- angr/angrdb/serializers/comments.py +60 -0
- angr/angrdb/serializers/funcs.py +61 -0
- angr/angrdb/serializers/kb.py +111 -0
- angr/angrdb/serializers/labels.py +59 -0
- angr/angrdb/serializers/loader.py +165 -0
- angr/angrdb/serializers/structured_code.py +167 -0
- angr/angrdb/serializers/variables.py +58 -0
- angr/angrdb/serializers/xrefs.py +48 -0
- angr/annocfg.py +317 -0
- angr/blade.py +431 -0
- angr/block.py +509 -0
- angr/callable.py +176 -0
- angr/calling_conventions.py +2613 -0
- angr/code_location.py +249 -0
- angr/codenode.py +145 -0
- angr/concretization_strategies/__init__.py +32 -0
- angr/concretization_strategies/any.py +17 -0
- angr/concretization_strategies/any_named.py +35 -0
- angr/concretization_strategies/base.py +81 -0
- angr/concretization_strategies/controlled_data.py +58 -0
- angr/concretization_strategies/eval.py +19 -0
- angr/concretization_strategies/logging.py +35 -0
- angr/concretization_strategies/max.py +25 -0
- angr/concretization_strategies/nonzero.py +16 -0
- angr/concretization_strategies/nonzero_range.py +22 -0
- angr/concretization_strategies/norepeats.py +37 -0
- angr/concretization_strategies/norepeats_range.py +37 -0
- angr/concretization_strategies/range.py +19 -0
- angr/concretization_strategies/signed_add.py +31 -0
- angr/concretization_strategies/single.py +15 -0
- angr/concretization_strategies/solutions.py +20 -0
- angr/concretization_strategies/unlimited_range.py +17 -0
- angr/distributed/__init__.py +9 -0
- angr/distributed/server.py +197 -0
- angr/distributed/worker.py +185 -0
- angr/emulator.py +144 -0
- angr/engines/__init__.py +69 -0
- angr/engines/ail/__init__.py +16 -0
- angr/engines/ail/callstack.py +58 -0
- angr/engines/ail/engine_light.py +903 -0
- angr/engines/ail/engine_successors.py +24 -0
- angr/engines/ail/setup.py +57 -0
- angr/engines/concrete.py +66 -0
- angr/engines/engine.py +29 -0
- angr/engines/failure.py +27 -0
- angr/engines/hook.py +93 -0
- angr/engines/icicle.py +294 -0
- angr/engines/light/__init__.py +23 -0
- angr/engines/light/data.py +681 -0
- angr/engines/light/engine.py +1297 -0
- angr/engines/pcode/__init__.py +9 -0
- angr/engines/pcode/behavior.py +998 -0
- angr/engines/pcode/cc.py +148 -0
- angr/engines/pcode/emulate.py +440 -0
- angr/engines/pcode/engine.py +242 -0
- angr/engines/pcode/lifter.py +1428 -0
- angr/engines/procedure.py +70 -0
- angr/engines/soot/__init__.py +5 -0
- angr/engines/soot/engine.py +410 -0
- angr/engines/soot/exceptions.py +17 -0
- angr/engines/soot/expressions/__init__.py +87 -0
- angr/engines/soot/expressions/arrayref.py +22 -0
- angr/engines/soot/expressions/base.py +21 -0
- angr/engines/soot/expressions/binop.py +28 -0
- angr/engines/soot/expressions/cast.py +22 -0
- angr/engines/soot/expressions/condition.py +35 -0
- angr/engines/soot/expressions/constants.py +47 -0
- angr/engines/soot/expressions/instanceOf.py +15 -0
- angr/engines/soot/expressions/instancefieldref.py +8 -0
- angr/engines/soot/expressions/invoke.py +114 -0
- angr/engines/soot/expressions/length.py +8 -0
- angr/engines/soot/expressions/local.py +8 -0
- angr/engines/soot/expressions/new.py +16 -0
- angr/engines/soot/expressions/newArray.py +54 -0
- angr/engines/soot/expressions/newMultiArray.py +86 -0
- angr/engines/soot/expressions/paramref.py +8 -0
- angr/engines/soot/expressions/phi.py +30 -0
- angr/engines/soot/expressions/staticfieldref.py +8 -0
- angr/engines/soot/expressions/thisref.py +7 -0
- angr/engines/soot/expressions/unsupported.py +7 -0
- angr/engines/soot/field_dispatcher.py +46 -0
- angr/engines/soot/method_dispatcher.py +46 -0
- angr/engines/soot/statements/__init__.py +44 -0
- angr/engines/soot/statements/assign.py +30 -0
- angr/engines/soot/statements/base.py +79 -0
- angr/engines/soot/statements/goto.py +14 -0
- angr/engines/soot/statements/identity.py +15 -0
- angr/engines/soot/statements/if_.py +19 -0
- angr/engines/soot/statements/invoke.py +12 -0
- angr/engines/soot/statements/return_.py +20 -0
- angr/engines/soot/statements/switch.py +41 -0
- angr/engines/soot/statements/throw.py +15 -0
- angr/engines/soot/values/__init__.py +38 -0
- angr/engines/soot/values/arrayref.py +122 -0
- angr/engines/soot/values/base.py +7 -0
- angr/engines/soot/values/constants.py +18 -0
- angr/engines/soot/values/instancefieldref.py +44 -0
- angr/engines/soot/values/local.py +18 -0
- angr/engines/soot/values/paramref.py +18 -0
- angr/engines/soot/values/staticfieldref.py +38 -0
- angr/engines/soot/values/strref.py +38 -0
- angr/engines/soot/values/thisref.py +149 -0
- angr/engines/successors.py +608 -0
- angr/engines/syscall.py +51 -0
- angr/engines/unicorn.py +490 -0
- angr/engines/vex/__init__.py +20 -0
- angr/engines/vex/claripy/__init__.py +5 -0
- angr/engines/vex/claripy/ccall.py +2097 -0
- angr/engines/vex/claripy/datalayer.py +141 -0
- angr/engines/vex/claripy/irop.py +1276 -0
- angr/engines/vex/heavy/__init__.py +16 -0
- angr/engines/vex/heavy/actions.py +231 -0
- angr/engines/vex/heavy/concretizers.py +403 -0
- angr/engines/vex/heavy/dirty.py +466 -0
- angr/engines/vex/heavy/heavy.py +370 -0
- angr/engines/vex/heavy/inspect.py +52 -0
- angr/engines/vex/heavy/resilience.py +85 -0
- angr/engines/vex/heavy/super_fastpath.py +34 -0
- angr/engines/vex/lifter.py +420 -0
- angr/engines/vex/light/__init__.py +11 -0
- angr/engines/vex/light/light.py +551 -0
- angr/engines/vex/light/resilience.py +74 -0
- angr/engines/vex/light/slicing.py +52 -0
- angr/errors.py +611 -0
- angr/exploration_techniques/__init__.py +53 -0
- angr/exploration_techniques/base.py +126 -0
- angr/exploration_techniques/bucketizer.py +94 -0
- angr/exploration_techniques/common.py +56 -0
- angr/exploration_techniques/dfs.py +37 -0
- angr/exploration_techniques/director.py +520 -0
- angr/exploration_techniques/driller_core.py +100 -0
- angr/exploration_techniques/explorer.py +152 -0
- angr/exploration_techniques/lengthlimiter.py +22 -0
- angr/exploration_techniques/local_loop_seer.py +65 -0
- angr/exploration_techniques/loop_seer.py +236 -0
- angr/exploration_techniques/manual_mergepoint.py +82 -0
- angr/exploration_techniques/memory_watcher.py +43 -0
- angr/exploration_techniques/oppologist.py +92 -0
- angr/exploration_techniques/slicecutor.py +118 -0
- angr/exploration_techniques/spiller.py +280 -0
- angr/exploration_techniques/spiller_db.py +27 -0
- angr/exploration_techniques/stochastic.py +56 -0
- angr/exploration_techniques/stub_stasher.py +19 -0
- angr/exploration_techniques/suggestions.py +159 -0
- angr/exploration_techniques/tech_builder.py +49 -0
- angr/exploration_techniques/threading.py +69 -0
- angr/exploration_techniques/timeout.py +34 -0
- angr/exploration_techniques/tracer.py +1098 -0
- angr/exploration_techniques/unique.py +106 -0
- angr/exploration_techniques/veritesting.py +37 -0
- angr/factory.py +413 -0
- angr/flirt/__init__.py +124 -0
- angr/flirt/build_sig.py +305 -0
- angr/graph_utils.py +0 -0
- angr/keyed_region.py +525 -0
- angr/knowledge_base.py +146 -0
- angr/knowledge_plugins/__init__.py +43 -0
- angr/knowledge_plugins/callsite_prototypes.py +95 -0
- angr/knowledge_plugins/cfg/__init__.py +18 -0
- angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
- angr/knowledge_plugins/cfg/cfg_model.py +1043 -0
- angr/knowledge_plugins/cfg/cfg_node.py +536 -0
- angr/knowledge_plugins/cfg/indirect_jump.py +131 -0
- angr/knowledge_plugins/cfg/memory_data.py +156 -0
- angr/knowledge_plugins/comments.py +16 -0
- angr/knowledge_plugins/custom_strings.py +38 -0
- angr/knowledge_plugins/data.py +22 -0
- angr/knowledge_plugins/debug_variables.py +216 -0
- angr/knowledge_plugins/functions/__init__.py +9 -0
- angr/knowledge_plugins/functions/function.py +1830 -0
- angr/knowledge_plugins/functions/function_manager.py +621 -0
- angr/knowledge_plugins/functions/function_parser.py +360 -0
- angr/knowledge_plugins/functions/soot_function.py +128 -0
- angr/knowledge_plugins/indirect_jumps.py +35 -0
- angr/knowledge_plugins/key_definitions/__init__.py +17 -0
- angr/knowledge_plugins/key_definitions/atoms.py +374 -0
- angr/knowledge_plugins/key_definitions/constants.py +29 -0
- angr/knowledge_plugins/key_definitions/definition.py +216 -0
- angr/knowledge_plugins/key_definitions/environment.py +96 -0
- angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +1020 -0
- angr/knowledge_plugins/key_definitions/liveness.py +165 -0
- angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
- angr/knowledge_plugins/key_definitions/tag.py +78 -0
- angr/knowledge_plugins/key_definitions/undefined.py +70 -0
- angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
- angr/knowledge_plugins/key_definitions/uses.py +178 -0
- angr/knowledge_plugins/labels.py +110 -0
- angr/knowledge_plugins/obfuscations.py +40 -0
- angr/knowledge_plugins/patches.py +126 -0
- angr/knowledge_plugins/plugin.py +24 -0
- angr/knowledge_plugins/propagations/__init__.py +10 -0
- angr/knowledge_plugins/propagations/prop_value.py +191 -0
- angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
- angr/knowledge_plugins/propagations/propagation_model.py +80 -0
- angr/knowledge_plugins/propagations/states.py +552 -0
- angr/knowledge_plugins/structured_code.py +63 -0
- angr/knowledge_plugins/types.py +95 -0
- angr/knowledge_plugins/variables/__init__.py +8 -0
- angr/knowledge_plugins/variables/variable_access.py +113 -0
- angr/knowledge_plugins/variables/variable_manager.py +1375 -0
- angr/knowledge_plugins/xrefs/__init__.py +12 -0
- angr/knowledge_plugins/xrefs/xref.py +150 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
- angr/knowledge_plugins/xrefs/xref_types.py +16 -0
- angr/misc/__init__.py +19 -0
- angr/misc/ansi.py +47 -0
- angr/misc/autoimport.py +90 -0
- angr/misc/bug_report.py +126 -0
- angr/misc/hookset.py +106 -0
- angr/misc/loggers.py +130 -0
- angr/misc/picklable_lock.py +46 -0
- angr/misc/plugins.py +289 -0
- angr/misc/telemetry.py +54 -0
- angr/misc/testing.py +24 -0
- angr/misc/ux.py +31 -0
- angr/procedures/__init__.py +12 -0
- angr/procedures/advapi32/__init__.py +0 -0
- angr/procedures/cgc/__init__.py +3 -0
- angr/procedures/cgc/_terminate.py +11 -0
- angr/procedures/cgc/allocate.py +75 -0
- angr/procedures/cgc/deallocate.py +67 -0
- angr/procedures/cgc/fdwait.py +65 -0
- angr/procedures/cgc/random.py +67 -0
- angr/procedures/cgc/receive.py +93 -0
- angr/procedures/cgc/transmit.py +65 -0
- angr/procedures/definitions/__init__.py +1043 -0
- angr/procedures/definitions/cgc.py +23 -0
- angr/procedures/definitions/common/glibc.json +3516 -0
- angr/procedures/definitions/gnulib.py +41 -0
- angr/procedures/definitions/libstdcpp.py +25 -0
- angr/procedures/definitions/linux_kernel.py +8382 -0
- angr/procedures/definitions/linux_loader.py +7 -0
- angr/procedures/definitions/macho_libsystem.py +18 -0
- angr/procedures/definitions/msvcr.py +25 -0
- angr/procedures/definitions/parse_glibc.py +77 -0
- angr/procedures/definitions/parse_syscalls_from_local_system.py +54 -0
- angr/procedures/definitions/parse_win32json.py +2540 -0
- angr/procedures/definitions/types_stl.py +22 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-4.json +24 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-6.json +18 -0
- angr/procedures/definitions/wdk/clfs.json +189 -0
- angr/procedures/definitions/wdk/fltmgr.json +813 -0
- angr/procedures/definitions/wdk/fwpkclnt.json +24 -0
- angr/procedures/definitions/wdk/fwpuclnt.json +453 -0
- angr/procedures/definitions/wdk/gdi32.json +528 -0
- angr/procedures/definitions/wdk/hal.json +96 -0
- angr/procedures/definitions/wdk/ksecdd.json +72 -0
- angr/procedures/definitions/wdk/ndis.json +336 -0
- angr/procedures/definitions/wdk/ntoskrnl.json +5158 -0
- angr/procedures/definitions/wdk/offreg.json +87 -0
- angr/procedures/definitions/wdk/pshed.json +33 -0
- angr/procedures/definitions/wdk/secur32.json +39 -0
- angr/procedures/definitions/wdk/vhfum.json +30 -0
- angr/procedures/definitions/win32/_types_win32.json +34480 -0
- angr/procedures/definitions/win32/aclui.json +24 -0
- angr/procedures/definitions/win32/activeds.json +81 -0
- angr/procedures/definitions/win32/advapi32.json +2505 -0
- angr/procedures/definitions/win32/advpack.json +165 -0
- angr/procedures/definitions/win32/amsi.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-1.json +45 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-3.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-apiquery-l2-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-backgroundtask-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-enclave-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-errorhandling-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-0.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-file-fromapp-l1-1-0.json +48 -0
- angr/procedures/definitions/win32/api-ms-win-core-handle-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-ioring-l1-1-0.json +51 -0
- angr/procedures/definitions/win32/api-ms-win-core-marshal-l1-1-0.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-3.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-5.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-6.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-7.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-8.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-path-l1-1-0.json +81 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-0.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-2.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-slapi-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-state-helpers-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-synch-l1-2-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-4.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-util-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-wow64-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-0.json +42 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-1.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-dx-d3dkmt-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-deviceinformation-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-expandedresources-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-2.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-4.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-mm-misc-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-net-isolation-l1-1-0.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-security-base-l1-2-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-5.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-1.json +33 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-wsl-api-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/apphelp.json +18 -0
- angr/procedures/definitions/win32/authz.json +114 -0
- angr/procedures/definitions/win32/avicap32.json +27 -0
- angr/procedures/definitions/win32/avifil32.json +195 -0
- angr/procedures/definitions/win32/avrt.json +57 -0
- angr/procedures/definitions/win32/bcp47mrm.json +21 -0
- angr/procedures/definitions/win32/bcrypt.json +174 -0
- angr/procedures/definitions/win32/bcryptprimitives.json +21 -0
- angr/procedures/definitions/win32/bluetoothapis.json +138 -0
- angr/procedures/definitions/win32/bthprops_cpl.json +33 -0
- angr/procedures/definitions/win32/cabinet.json +81 -0
- angr/procedures/definitions/win32/certadm.json +69 -0
- angr/procedures/definitions/win32/certpoleng.json +39 -0
- angr/procedures/definitions/win32/cfgmgr32.json +732 -0
- angr/procedures/definitions/win32/chakra.json +270 -0
- angr/procedures/definitions/win32/cldapi.json +123 -0
- angr/procedures/definitions/win32/clfsw32.json +192 -0
- angr/procedures/definitions/win32/clusapi.json +855 -0
- angr/procedures/definitions/win32/comctl32.json +360 -0
- angr/procedures/definitions/win32/comdlg32.json +78 -0
- angr/procedures/definitions/win32/compstui.json +27 -0
- angr/procedures/definitions/win32/computecore.json +177 -0
- angr/procedures/definitions/win32/computenetwork.json +144 -0
- angr/procedures/definitions/win32/computestorage.json +51 -0
- angr/procedures/definitions/win32/comsvcs.json +36 -0
- angr/procedures/definitions/win32/credui.json +72 -0
- angr/procedures/definitions/win32/crypt32.json +702 -0
- angr/procedures/definitions/win32/cryptnet.json +30 -0
- angr/procedures/definitions/win32/cryptui.json +45 -0
- angr/procedures/definitions/win32/cryptxml.json +72 -0
- angr/procedures/definitions/win32/cscapi.json +27 -0
- angr/procedures/definitions/win32/d2d1.json +54 -0
- angr/procedures/definitions/win32/d3d10.json +96 -0
- angr/procedures/definitions/win32/d3d10_1.json +21 -0
- angr/procedures/definitions/win32/d3d11.json +24 -0
- angr/procedures/definitions/win32/d3d12.json +39 -0
- angr/procedures/definitions/win32/d3d9.json +48 -0
- angr/procedures/definitions/win32/d3dcompiler_47.json +93 -0
- angr/procedures/definitions/win32/d3dcsx.json +42 -0
- angr/procedures/definitions/win32/davclnt.json +69 -0
- angr/procedures/definitions/win32/dbgeng.json +27 -0
- angr/procedures/definitions/win32/dbghelp.json +663 -0
- angr/procedures/definitions/win32/dbgmodel.json +18 -0
- angr/procedures/definitions/win32/dciman32.json +75 -0
- angr/procedures/definitions/win32/dcomp.json +51 -0
- angr/procedures/definitions/win32/ddraw.json +36 -0
- angr/procedures/definitions/win32/deviceaccess.json +18 -0
- angr/procedures/definitions/win32/dflayout.json +18 -0
- angr/procedures/definitions/win32/dhcpcsvc.json +60 -0
- angr/procedures/definitions/win32/dhcpcsvc6.json +33 -0
- angr/procedures/definitions/win32/dhcpsapi.json +603 -0
- angr/procedures/definitions/win32/diagnosticdataquery.json +120 -0
- angr/procedures/definitions/win32/dinput8.json +18 -0
- angr/procedures/definitions/win32/directml.json +21 -0
- angr/procedures/definitions/win32/dmprocessxmlfiltered.json +18 -0
- angr/procedures/definitions/win32/dnsapi.json +207 -0
- angr/procedures/definitions/win32/drt.json +63 -0
- angr/procedures/definitions/win32/drtprov.json +42 -0
- angr/procedures/definitions/win32/drttransport.json +21 -0
- angr/procedures/definitions/win32/dsound.json +45 -0
- angr/procedures/definitions/win32/dsparse.json +72 -0
- angr/procedures/definitions/win32/dsprop.json +36 -0
- angr/procedures/definitions/win32/dssec.json +27 -0
- angr/procedures/definitions/win32/dsuiext.json +27 -0
- angr/procedures/definitions/win32/dwmapi.json +108 -0
- angr/procedures/definitions/win32/dwrite.json +18 -0
- angr/procedures/definitions/win32/dxcompiler.json +21 -0
- angr/procedures/definitions/win32/dxcore.json +18 -0
- angr/procedures/definitions/win32/dxgi.json +33 -0
- angr/procedures/definitions/win32/dxva2.json +129 -0
- angr/procedures/definitions/win32/eappcfg.json +57 -0
- angr/procedures/definitions/win32/eappprxy.json +69 -0
- angr/procedures/definitions/win32/efswrt.json +21 -0
- angr/procedures/definitions/win32/elscore.json +30 -0
- angr/procedures/definitions/win32/esent.json +702 -0
- angr/procedures/definitions/win32/evr.json +36 -0
- angr/procedures/definitions/win32/faultrep.json +27 -0
- angr/procedures/definitions/win32/fhsvcctl.json +36 -0
- angr/procedures/definitions/win32/firewallapi.json +24 -0
- angr/procedures/definitions/win32/fltlib.json +99 -0
- angr/procedures/definitions/win32/fontsub.json +21 -0
- angr/procedures/definitions/win32/forceinline.json +24 -0
- angr/procedures/definitions/win32/fwpuclnt.json +591 -0
- angr/procedures/definitions/win32/fxsutility.json +21 -0
- angr/procedures/definitions/win32/gdi32.json +1308 -0
- angr/procedures/definitions/win32/gdiplus.json +1902 -0
- angr/procedures/definitions/win32/glu32.json +171 -0
- angr/procedures/definitions/win32/gpedit.json +33 -0
- angr/procedures/definitions/win32/hhctrl_ocx.json +21 -0
- angr/procedures/definitions/win32/hid.json +150 -0
- angr/procedures/definitions/win32/hlink.json +99 -0
- angr/procedures/definitions/win32/hrtfapo.json +18 -0
- angr/procedures/definitions/win32/httpapi.json +144 -0
- angr/procedures/definitions/win32/icm32.json +78 -0
- angr/procedures/definitions/win32/icmui.json +21 -0
- angr/procedures/definitions/win32/icu.json +3090 -0
- angr/procedures/definitions/win32/ieframe.json +102 -0
- angr/procedures/definitions/win32/imagehlp.json +84 -0
- angr/procedures/definitions/win32/imgutil.json +42 -0
- angr/procedures/definitions/win32/imm32.json +261 -0
- angr/procedures/definitions/win32/infocardapi.json +66 -0
- angr/procedures/definitions/win32/inkobjcore.json +96 -0
- angr/procedures/definitions/win32/iphlpapi.json +618 -0
- angr/procedures/definitions/win32/iscsidsc.json +252 -0
- angr/procedures/definitions/win32/isolatedwindowsenvironmentutils.json +21 -0
- angr/procedures/definitions/win32/kernel32.json +4566 -0
- angr/procedures/definitions/win32/kernelbase.json +33 -0
- angr/procedures/definitions/win32/keycredmgr.json +27 -0
- angr/procedures/definitions/win32/ksproxy_ax.json +33 -0
- angr/procedures/definitions/win32/ksuser.json +39 -0
- angr/procedures/definitions/win32/ktmw32.json +132 -0
- angr/procedures/definitions/win32/licenseprotection.json +21 -0
- angr/procedures/definitions/win32/loadperf.json +51 -0
- angr/procedures/definitions/win32/magnification.json +72 -0
- angr/procedures/definitions/win32/mapi32.json +213 -0
- angr/procedures/definitions/win32/mdmlocalmanagement.json +24 -0
- angr/procedures/definitions/win32/mdmregistration.json +60 -0
- angr/procedures/definitions/win32/mf.json +201 -0
- angr/procedures/definitions/win32/mfcore.json +21 -0
- angr/procedures/definitions/win32/mfplat.json +450 -0
- angr/procedures/definitions/win32/mfplay.json +18 -0
- angr/procedures/definitions/win32/mfreadwrite.json +30 -0
- angr/procedures/definitions/win32/mfsensorgroup.json +45 -0
- angr/procedures/definitions/win32/mfsrcsnk.json +21 -0
- angr/procedures/definitions/win32/mgmtapi.json +42 -0
- angr/procedures/definitions/win32/mi.json +18 -0
- angr/procedures/definitions/win32/mmdevapi.json +18 -0
- angr/procedures/definitions/win32/mpr.json +156 -0
- angr/procedures/definitions/win32/mprapi.json +351 -0
- angr/procedures/definitions/win32/mqrt.json +117 -0
- angr/procedures/definitions/win32/mrmsupport.json +96 -0
- angr/procedures/definitions/win32/msacm32.json +141 -0
- angr/procedures/definitions/win32/msajapi.json +1656 -0
- angr/procedures/definitions/win32/mscms.json +252 -0
- angr/procedures/definitions/win32/mscoree.json +96 -0
- angr/procedures/definitions/win32/msctfmonitor.json +24 -0
- angr/procedures/definitions/win32/msdelta.json +63 -0
- angr/procedures/definitions/win32/msdmo.json +48 -0
- angr/procedures/definitions/win32/msdrm.json +267 -0
- angr/procedures/definitions/win32/msi.json +807 -0
- angr/procedures/definitions/win32/msimg32.json +24 -0
- angr/procedures/definitions/win32/mspatcha.json +63 -0
- angr/procedures/definitions/win32/mspatchc.json +42 -0
- angr/procedures/definitions/win32/msports.json +36 -0
- angr/procedures/definitions/win32/msrating.json +72 -0
- angr/procedures/definitions/win32/mssign32.json +45 -0
- angr/procedures/definitions/win32/mstask.json +21 -0
- angr/procedures/definitions/win32/msvfw32.json +144 -0
- angr/procedures/definitions/win32/mswsock.json +63 -0
- angr/procedures/definitions/win32/mtxdm.json +18 -0
- angr/procedures/definitions/win32/ncrypt.json +132 -0
- angr/procedures/definitions/win32/ndfapi.json +63 -0
- angr/procedures/definitions/win32/netapi32.json +633 -0
- angr/procedures/definitions/win32/netsh.json +39 -0
- angr/procedures/definitions/win32/netshell.json +21 -0
- angr/procedures/definitions/win32/newdev.json +48 -0
- angr/procedures/definitions/win32/ninput.json +105 -0
- angr/procedures/definitions/win32/normaliz.json +21 -0
- angr/procedures/definitions/win32/ntdll.json +234 -0
- angr/procedures/definitions/win32/ntdllk.json +18 -0
- angr/procedures/definitions/win32/ntdsapi.json +258 -0
- angr/procedures/definitions/win32/ntlanman.json +45 -0
- angr/procedures/definitions/win32/odbc32.json +477 -0
- angr/procedures/definitions/win32/odbcbcp.json +96 -0
- angr/procedures/definitions/win32/ole32.json +966 -0
- angr/procedures/definitions/win32/oleacc.json +66 -0
- angr/procedures/definitions/win32/oleaut32.json +1230 -0
- angr/procedures/definitions/win32/oledlg.json +84 -0
- angr/procedures/definitions/win32/ondemandconnroutehelper.json +30 -0
- angr/procedures/definitions/win32/opengl32.json +1080 -0
- angr/procedures/definitions/win32/opmxbox.json +24 -0
- angr/procedures/definitions/win32/p2p.json +339 -0
- angr/procedures/definitions/win32/p2pgraph.json +126 -0
- angr/procedures/definitions/win32/pdh.json +309 -0
- angr/procedures/definitions/win32/peerdist.json +99 -0
- angr/procedures/definitions/win32/powrprof.json +267 -0
- angr/procedures/definitions/win32/prntvpt.json +48 -0
- angr/procedures/definitions/win32/projectedfslib.json +72 -0
- angr/procedures/definitions/win32/propsys.json +669 -0
- angr/procedures/definitions/win32/psapi.json +96 -0
- angr/procedures/definitions/win32/quartz.json +21 -0
- angr/procedures/definitions/win32/query.json +27 -0
- angr/procedures/definitions/win32/qwave.json +48 -0
- angr/procedures/definitions/win32/rasapi32.json +267 -0
- angr/procedures/definitions/win32/rasdlg.json +33 -0
- angr/procedures/definitions/win32/resutils.json +375 -0
- angr/procedures/definitions/win32/rpcns4.json +198 -0
- angr/procedures/definitions/win32/rpcproxy.json +27 -0
- angr/procedures/definitions/win32/rpcrt4.json +1356 -0
- angr/procedures/definitions/win32/rstrtmgr.json +48 -0
- angr/procedures/definitions/win32/rtm.json +243 -0
- angr/procedures/definitions/win32/rtutils.json +138 -0
- angr/procedures/definitions/win32/rtworkq.json +114 -0
- angr/procedures/definitions/win32/sas.json +18 -0
- angr/procedures/definitions/win32/scarddlg.json +30 -0
- angr/procedures/definitions/win32/schannel.json +42 -0
- angr/procedures/definitions/win32/sechost.json +21 -0
- angr/procedures/definitions/win32/secur32.json +282 -0
- angr/procedures/definitions/win32/sensapi.json +24 -0
- angr/procedures/definitions/win32/sensorsutilsv2.json +135 -0
- angr/procedures/definitions/win32/setupapi.json +1017 -0
- angr/procedures/definitions/win32/sfc.json +33 -0
- angr/procedures/definitions/win32/shdocvw.json +24 -0
- angr/procedures/definitions/win32/shell32.json +747 -0
- angr/procedures/definitions/win32/shlwapi.json +1095 -0
- angr/procedures/definitions/win32/slc.json +111 -0
- angr/procedures/definitions/win32/slcext.json +27 -0
- angr/procedures/definitions/win32/slwga.json +18 -0
- angr/procedures/definitions/win32/snmpapi.json +93 -0
- angr/procedures/definitions/win32/spoolss.json +93 -0
- angr/procedures/definitions/win32/srclient.json +18 -0
- angr/procedures/definitions/win32/srpapi.json +48 -0
- angr/procedures/definitions/win32/sspicli.json +36 -0
- angr/procedures/definitions/win32/sti.json +18 -0
- angr/procedures/definitions/win32/t2embed.json +57 -0
- angr/procedures/definitions/win32/tapi32.json +762 -0
- angr/procedures/definitions/win32/tbs.json +57 -0
- angr/procedures/definitions/win32/tdh.json +96 -0
- angr/procedures/definitions/win32/tokenbinding.json +45 -0
- angr/procedures/definitions/win32/traffic.json +75 -0
- angr/procedures/definitions/win32/txfw32.json +42 -0
- angr/procedures/definitions/win32/ualapi.json +27 -0
- angr/procedures/definitions/win32/uiautomationcore.json +309 -0
- angr/procedures/definitions/win32/urlmon.json +246 -0
- angr/procedures/definitions/win32/user32.json +2298 -0
- angr/procedures/definitions/win32/userenv.json +147 -0
- angr/procedures/definitions/win32/usp10.json +135 -0
- angr/procedures/definitions/win32/uxtheme.json +246 -0
- angr/procedures/definitions/win32/verifier.json +18 -0
- angr/procedures/definitions/win32/version.json +57 -0
- angr/procedures/definitions/win32/vertdll.json +36 -0
- angr/procedures/definitions/win32/virtdisk.json +102 -0
- angr/procedures/definitions/win32/vmdevicehost.json +54 -0
- angr/procedures/definitions/win32/vmsavedstatedumpprovider.json +144 -0
- angr/procedures/definitions/win32/vssapi.json +18 -0
- angr/procedures/definitions/win32/wcmapi.json +30 -0
- angr/procedures/definitions/win32/wdsbp.json +36 -0
- angr/procedures/definitions/win32/wdsclientapi.json +126 -0
- angr/procedures/definitions/win32/wdsmc.json +33 -0
- angr/procedures/definitions/win32/wdspxe.json +108 -0
- angr/procedures/definitions/win32/wdstptc.json +54 -0
- angr/procedures/definitions/win32/webauthn.json +54 -0
- angr/procedures/definitions/win32/webservices.json +594 -0
- angr/procedures/definitions/win32/websocket.json +54 -0
- angr/procedures/definitions/win32/wecapi.json +60 -0
- angr/procedures/definitions/win32/wer.json +78 -0
- angr/procedures/definitions/win32/wevtapi.json +120 -0
- angr/procedures/definitions/win32/winbio.json +177 -0
- angr/procedures/definitions/win32/windows_ai_machinelearning.json +18 -0
- angr/procedures/definitions/win32/windows_media_mediacontrol.json +39 -0
- angr/procedures/definitions/win32/windows_networking.json +18 -0
- angr/procedures/definitions/win32/windows_ui_xaml.json +21 -0
- angr/procedures/definitions/win32/windowscodecs.json +42 -0
- angr/procedures/definitions/win32/winfax.json +183 -0
- angr/procedures/definitions/win32/winhttp.json +183 -0
- angr/procedures/definitions/win32/winhvemulation.json +27 -0
- angr/procedures/definitions/win32/winhvplatform.json +213 -0
- angr/procedures/definitions/win32/wininet.json +903 -0
- angr/procedures/definitions/win32/winml.json +18 -0
- angr/procedures/definitions/win32/winmm.json +543 -0
- angr/procedures/definitions/win32/winscard.json +225 -0
- angr/procedures/definitions/win32/winspool_drv.json +531 -0
- angr/procedures/definitions/win32/wintrust.json +195 -0
- angr/procedures/definitions/win32/winusb.json +117 -0
- angr/procedures/definitions/win32/wlanapi.json +195 -0
- angr/procedures/definitions/win32/wlanui.json +18 -0
- angr/procedures/definitions/win32/wldap32.json +744 -0
- angr/procedures/definitions/win32/wldp.json +42 -0
- angr/procedures/definitions/win32/wmvcore.json +48 -0
- angr/procedures/definitions/win32/wnvapi.json +21 -0
- angr/procedures/definitions/win32/wofutil.json +48 -0
- angr/procedures/definitions/win32/ws2_32.json +495 -0
- angr/procedures/definitions/win32/wscapi.json +33 -0
- angr/procedures/definitions/win32/wsclient.json +24 -0
- angr/procedures/definitions/win32/wsdapi.json +111 -0
- angr/procedures/definitions/win32/wsmsvc.json +114 -0
- angr/procedures/definitions/win32/wsnmp32.json +162 -0
- angr/procedures/definitions/win32/wtsapi32.json +204 -0
- angr/procedures/definitions/win32/xaudio2_8.json +27 -0
- angr/procedures/definitions/win32/xinput1_4.json +36 -0
- angr/procedures/definitions/win32/xmllite.json +33 -0
- angr/procedures/definitions/win32/xolehlp.json +27 -0
- angr/procedures/definitions/win32/xpsprint.json +21 -0
- angr/procedures/glibc/__ctype_b_loc.py +21 -0
- angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
- angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
- angr/procedures/glibc/__errno_location.py +7 -0
- angr/procedures/glibc/__init__.py +3 -0
- angr/procedures/glibc/__libc_init.py +37 -0
- angr/procedures/glibc/__libc_start_main.py +301 -0
- angr/procedures/glibc/dynamic_loading.py +20 -0
- angr/procedures/glibc/scanf.py +19 -0
- angr/procedures/glibc/sscanf.py +10 -0
- angr/procedures/gnulib/__init__.py +3 -0
- angr/procedures/gnulib/xalloc_die.py +14 -0
- angr/procedures/gnulib/xstrtol_fatal.py +14 -0
- angr/procedures/java/__init__.py +42 -0
- angr/procedures/java/unconstrained.py +65 -0
- angr/procedures/java_io/__init__.py +0 -0
- angr/procedures/java_io/read.py +12 -0
- angr/procedures/java_io/write.py +17 -0
- angr/procedures/java_jni/__init__.py +482 -0
- angr/procedures/java_jni/array_operations.py +312 -0
- angr/procedures/java_jni/class_and_interface_operations.py +31 -0
- angr/procedures/java_jni/field_access.py +173 -0
- angr/procedures/java_jni/global_and_local_refs.py +57 -0
- angr/procedures/java_jni/method_calls.py +365 -0
- angr/procedures/java_jni/not_implemented.py +26 -0
- angr/procedures/java_jni/object_operations.py +94 -0
- angr/procedures/java_jni/string_operations.py +87 -0
- angr/procedures/java_jni/version_information.py +12 -0
- angr/procedures/java_lang/__init__.py +0 -0
- angr/procedures/java_lang/character.py +30 -0
- angr/procedures/java_lang/double.py +24 -0
- angr/procedures/java_lang/exit.py +13 -0
- angr/procedures/java_lang/getsimplename.py +18 -0
- angr/procedures/java_lang/integer.py +43 -0
- angr/procedures/java_lang/load_library.py +9 -0
- angr/procedures/java_lang/math.py +15 -0
- angr/procedures/java_lang/string.py +78 -0
- angr/procedures/java_lang/stringbuilder.py +44 -0
- angr/procedures/java_lang/system.py +18 -0
- angr/procedures/java_util/__init__.py +0 -0
- angr/procedures/java_util/collection.py +35 -0
- angr/procedures/java_util/iterator.py +46 -0
- angr/procedures/java_util/list.py +99 -0
- angr/procedures/java_util/map.py +131 -0
- angr/procedures/java_util/random.py +14 -0
- angr/procedures/java_util/scanner_nextline.py +23 -0
- angr/procedures/libc/__init__.py +3 -0
- angr/procedures/libc/abort.py +9 -0
- angr/procedures/libc/access.py +13 -0
- angr/procedures/libc/atoi.py +14 -0
- angr/procedures/libc/atol.py +13 -0
- angr/procedures/libc/calloc.py +8 -0
- angr/procedures/libc/closelog.py +10 -0
- angr/procedures/libc/err.py +14 -0
- angr/procedures/libc/error.py +54 -0
- angr/procedures/libc/exit.py +11 -0
- angr/procedures/libc/fclose.py +19 -0
- angr/procedures/libc/feof.py +21 -0
- angr/procedures/libc/fflush.py +16 -0
- angr/procedures/libc/fgetc.py +27 -0
- angr/procedures/libc/fgets.py +69 -0
- angr/procedures/libc/fopen.py +63 -0
- angr/procedures/libc/fprintf.py +25 -0
- angr/procedures/libc/fputc.py +23 -0
- angr/procedures/libc/fputs.py +24 -0
- angr/procedures/libc/fread.py +24 -0
- angr/procedures/libc/free.py +9 -0
- angr/procedures/libc/fscanf.py +20 -0
- angr/procedures/libc/fseek.py +34 -0
- angr/procedures/libc/ftell.py +22 -0
- angr/procedures/libc/fwrite.py +19 -0
- angr/procedures/libc/getchar.py +13 -0
- angr/procedures/libc/getdelim.py +99 -0
- angr/procedures/libc/getegid.py +8 -0
- angr/procedures/libc/geteuid.py +8 -0
- angr/procedures/libc/getgid.py +8 -0
- angr/procedures/libc/gets.py +68 -0
- angr/procedures/libc/getuid.py +8 -0
- angr/procedures/libc/malloc.py +12 -0
- angr/procedures/libc/memcmp.py +69 -0
- angr/procedures/libc/memcpy.py +45 -0
- angr/procedures/libc/memset.py +72 -0
- angr/procedures/libc/openlog.py +10 -0
- angr/procedures/libc/perror.py +13 -0
- angr/procedures/libc/printf.py +34 -0
- angr/procedures/libc/putchar.py +13 -0
- angr/procedures/libc/puts.py +19 -0
- angr/procedures/libc/rand.py +8 -0
- angr/procedures/libc/realloc.py +8 -0
- angr/procedures/libc/rewind.py +12 -0
- angr/procedures/libc/scanf.py +20 -0
- angr/procedures/libc/setbuf.py +9 -0
- angr/procedures/libc/setvbuf.py +7 -0
- angr/procedures/libc/snprintf.py +36 -0
- angr/procedures/libc/sprintf.py +25 -0
- angr/procedures/libc/srand.py +7 -0
- angr/procedures/libc/sscanf.py +13 -0
- angr/procedures/libc/stpcpy.py +18 -0
- angr/procedures/libc/strcat.py +14 -0
- angr/procedures/libc/strchr.py +48 -0
- angr/procedures/libc/strcmp.py +31 -0
- angr/procedures/libc/strcpy.py +13 -0
- angr/procedures/libc/strlen.py +114 -0
- angr/procedures/libc/strncat.py +19 -0
- angr/procedures/libc/strncmp.py +183 -0
- angr/procedures/libc/strncpy.py +22 -0
- angr/procedures/libc/strnlen.py +13 -0
- angr/procedures/libc/strstr.py +101 -0
- angr/procedures/libc/strtol.py +261 -0
- angr/procedures/libc/strtoul.py +9 -0
- angr/procedures/libc/system.py +13 -0
- angr/procedures/libc/time.py +9 -0
- angr/procedures/libc/tmpnam.py +20 -0
- angr/procedures/libc/tolower.py +10 -0
- angr/procedures/libc/toupper.py +10 -0
- angr/procedures/libc/ungetc.py +20 -0
- angr/procedures/libc/vsnprintf.py +17 -0
- angr/procedures/libc/wchar.py +16 -0
- angr/procedures/libstdcpp/__init__.py +0 -0
- angr/procedures/libstdcpp/_unwind_resume.py +11 -0
- angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
- angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
- angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
- angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
- angr/procedures/libstdcpp/std__terminate.py +13 -0
- angr/procedures/linux_kernel/__init__.py +3 -0
- angr/procedures/linux_kernel/access.py +18 -0
- angr/procedures/linux_kernel/arch_prctl.py +34 -0
- angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
- angr/procedures/linux_kernel/brk.py +18 -0
- angr/procedures/linux_kernel/cwd.py +28 -0
- angr/procedures/linux_kernel/fstat.py +138 -0
- angr/procedures/linux_kernel/fstat64.py +170 -0
- angr/procedures/linux_kernel/futex.py +17 -0
- angr/procedures/linux_kernel/getegid.py +17 -0
- angr/procedures/linux_kernel/geteuid.py +17 -0
- angr/procedures/linux_kernel/getgid.py +17 -0
- angr/procedures/linux_kernel/getpid.py +14 -0
- angr/procedures/linux_kernel/getrlimit.py +24 -0
- angr/procedures/linux_kernel/gettid.py +9 -0
- angr/procedures/linux_kernel/getuid.py +17 -0
- angr/procedures/linux_kernel/iovec.py +47 -0
- angr/procedures/linux_kernel/lseek.py +42 -0
- angr/procedures/linux_kernel/mmap.py +16 -0
- angr/procedures/linux_kernel/mprotect.py +42 -0
- angr/procedures/linux_kernel/munmap.py +8 -0
- angr/procedures/linux_kernel/openat.py +26 -0
- angr/procedures/linux_kernel/set_tid_address.py +8 -0
- angr/procedures/linux_kernel/sigaction.py +19 -0
- angr/procedures/linux_kernel/sigprocmask.py +23 -0
- angr/procedures/linux_kernel/stat.py +23 -0
- angr/procedures/linux_kernel/sysinfo.py +59 -0
- angr/procedures/linux_kernel/tgkill.py +10 -0
- angr/procedures/linux_kernel/time.py +34 -0
- angr/procedures/linux_kernel/uid.py +30 -0
- angr/procedures/linux_kernel/uname.py +29 -0
- angr/procedures/linux_kernel/unlink.py +22 -0
- angr/procedures/linux_kernel/vsyscall.py +16 -0
- angr/procedures/linux_loader/__init__.py +3 -0
- angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
- angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
- angr/procedures/linux_loader/sim_loader.py +54 -0
- angr/procedures/linux_loader/tls.py +40 -0
- angr/procedures/msvcr/__getmainargs.py +16 -0
- angr/procedures/msvcr/__init__.py +4 -0
- angr/procedures/msvcr/_initterm.py +38 -0
- angr/procedures/msvcr/fmode.py +31 -0
- angr/procedures/ntdll/__init__.py +0 -0
- angr/procedures/ntdll/exceptions.py +60 -0
- angr/procedures/posix/__init__.py +3 -0
- angr/procedures/posix/accept.py +29 -0
- angr/procedures/posix/bind.py +13 -0
- angr/procedures/posix/bzero.py +9 -0
- angr/procedures/posix/chroot.py +27 -0
- angr/procedures/posix/close.py +9 -0
- angr/procedures/posix/closedir.py +7 -0
- angr/procedures/posix/dup.py +56 -0
- angr/procedures/posix/fcntl.py +10 -0
- angr/procedures/posix/fdopen.py +76 -0
- angr/procedures/posix/fileno.py +18 -0
- angr/procedures/posix/fork.py +13 -0
- angr/procedures/posix/getenv.py +35 -0
- angr/procedures/posix/gethostbyname.py +43 -0
- angr/procedures/posix/getpass.py +19 -0
- angr/procedures/posix/getsockopt.py +11 -0
- angr/procedures/posix/htonl.py +11 -0
- angr/procedures/posix/htons.py +11 -0
- angr/procedures/posix/inet_ntoa.py +59 -0
- angr/procedures/posix/listen.py +13 -0
- angr/procedures/posix/mmap.py +144 -0
- angr/procedures/posix/open.py +18 -0
- angr/procedures/posix/opendir.py +10 -0
- angr/procedures/posix/poll.py +55 -0
- angr/procedures/posix/pread64.py +46 -0
- angr/procedures/posix/pthread.py +87 -0
- angr/procedures/posix/pwrite64.py +46 -0
- angr/procedures/posix/read.py +13 -0
- angr/procedures/posix/readdir.py +62 -0
- angr/procedures/posix/recv.py +13 -0
- angr/procedures/posix/recvfrom.py +13 -0
- angr/procedures/posix/select.py +48 -0
- angr/procedures/posix/send.py +23 -0
- angr/procedures/posix/setsockopt.py +9 -0
- angr/procedures/posix/sigaction.py +23 -0
- angr/procedures/posix/sim_time.py +48 -0
- angr/procedures/posix/sleep.py +8 -0
- angr/procedures/posix/socket.py +18 -0
- angr/procedures/posix/strcasecmp.py +26 -0
- angr/procedures/posix/strdup.py +18 -0
- angr/procedures/posix/strtok_r.py +64 -0
- angr/procedures/posix/syslog.py +15 -0
- angr/procedures/posix/tz.py +9 -0
- angr/procedures/posix/unlink.py +11 -0
- angr/procedures/posix/usleep.py +8 -0
- angr/procedures/posix/write.py +13 -0
- angr/procedures/procedure_dict.py +50 -0
- angr/procedures/stubs/CallReturn.py +13 -0
- angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
- angr/procedures/stubs/Nop.py +7 -0
- angr/procedures/stubs/PathTerminator.py +9 -0
- angr/procedures/stubs/Redirect.py +18 -0
- angr/procedures/stubs/ReturnChar.py +11 -0
- angr/procedures/stubs/ReturnUnconstrained.py +24 -0
- angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
- angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
- angr/procedures/stubs/UserHook.py +18 -0
- angr/procedures/stubs/__init__.py +3 -0
- angr/procedures/stubs/b64_decode.py +15 -0
- angr/procedures/stubs/caller.py +14 -0
- angr/procedures/stubs/crazy_scanf.py +20 -0
- angr/procedures/stubs/format_parser.py +669 -0
- angr/procedures/stubs/syscall_stub.py +24 -0
- angr/procedures/testing/__init__.py +3 -0
- angr/procedures/testing/manyargs.py +9 -0
- angr/procedures/testing/retreg.py +8 -0
- angr/procedures/tracer/__init__.py +4 -0
- angr/procedures/tracer/random.py +9 -0
- angr/procedures/tracer/receive.py +23 -0
- angr/procedures/tracer/transmit.py +26 -0
- angr/procedures/uclibc/__init__.py +3 -0
- angr/procedures/uclibc/__uClibc_main.py +10 -0
- angr/procedures/win32/EncodePointer.py +7 -0
- angr/procedures/win32/ExitProcess.py +9 -0
- angr/procedures/win32/GetCommandLine.py +12 -0
- angr/procedures/win32/GetCurrentProcessId.py +7 -0
- angr/procedures/win32/GetCurrentThreadId.py +7 -0
- angr/procedures/win32/GetLastInputInfo.py +40 -0
- angr/procedures/win32/GetModuleHandle.py +29 -0
- angr/procedures/win32/GetProcessAffinityMask.py +37 -0
- angr/procedures/win32/InterlockedExchange.py +15 -0
- angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
- angr/procedures/win32/VirtualAlloc.py +114 -0
- angr/procedures/win32/VirtualProtect.py +60 -0
- angr/procedures/win32/__init__.py +3 -0
- angr/procedures/win32/critical_section.py +12 -0
- angr/procedures/win32/dynamic_loading.py +104 -0
- angr/procedures/win32/file_handles.py +47 -0
- angr/procedures/win32/gethostbyname.py +12 -0
- angr/procedures/win32/heap.py +45 -0
- angr/procedures/win32/is_bad_ptr.py +26 -0
- angr/procedures/win32/local_storage.py +88 -0
- angr/procedures/win32/mutex.py +11 -0
- angr/procedures/win32/sim_time.py +135 -0
- angr/procedures/win32/system_paths.py +35 -0
- angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
- angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
- angr/procedures/win32_kernel/__fastfail.py +15 -0
- angr/procedures/win32_kernel/__init__.py +3 -0
- angr/procedures/win_user32/__init__.py +0 -0
- angr/procedures/win_user32/chars.py +15 -0
- angr/procedures/win_user32/keyboard.py +14 -0
- angr/procedures/win_user32/messagebox.py +49 -0
- angr/project.py +860 -0
- angr/protos/__init__.py +19 -0
- angr/protos/cfg_pb2.py +42 -0
- angr/protos/function_pb2.py +38 -0
- angr/protos/primitives_pb2.py +59 -0
- angr/protos/variables_pb2.py +55 -0
- angr/protos/xrefs_pb2.py +36 -0
- angr/py.typed +1 -0
- angr/rustylib.cpython-311-darwin.so +0 -0
- angr/serializable.py +66 -0
- angr/sim_manager.py +971 -0
- angr/sim_options.py +436 -0
- angr/sim_procedure.py +626 -0
- angr/sim_state.py +926 -0
- angr/sim_state_options.py +403 -0
- angr/sim_type.py +4026 -0
- angr/sim_variable.py +470 -0
- angr/simos/__init__.py +47 -0
- angr/simos/cgc.py +153 -0
- angr/simos/javavm.py +458 -0
- angr/simos/linux.py +509 -0
- angr/simos/simos.py +444 -0
- angr/simos/snimmuc_nxp.py +149 -0
- angr/simos/userland.py +163 -0
- angr/simos/windows.py +615 -0
- angr/simos/xbox.py +32 -0
- angr/slicer.py +352 -0
- angr/state_hierarchy.py +262 -0
- angr/state_plugins/__init__.py +84 -0
- angr/state_plugins/callstack.py +478 -0
- angr/state_plugins/cgc.py +155 -0
- angr/state_plugins/debug_variables.py +192 -0
- angr/state_plugins/filesystem.py +463 -0
- angr/state_plugins/gdb.py +148 -0
- angr/state_plugins/globals.py +65 -0
- angr/state_plugins/heap/__init__.py +15 -0
- angr/state_plugins/heap/heap_base.py +128 -0
- angr/state_plugins/heap/heap_brk.py +136 -0
- angr/state_plugins/heap/heap_freelist.py +213 -0
- angr/state_plugins/heap/heap_libc.py +46 -0
- angr/state_plugins/heap/heap_ptmalloc.py +620 -0
- angr/state_plugins/heap/utils.py +22 -0
- angr/state_plugins/history.py +564 -0
- angr/state_plugins/inspect.py +375 -0
- angr/state_plugins/javavm_classloader.py +134 -0
- angr/state_plugins/jni_references.py +95 -0
- angr/state_plugins/libc.py +1263 -0
- angr/state_plugins/light_registers.py +168 -0
- angr/state_plugins/log.py +84 -0
- angr/state_plugins/loop_data.py +92 -0
- angr/state_plugins/plugin.py +176 -0
- angr/state_plugins/posix.py +703 -0
- angr/state_plugins/preconstrainer.py +196 -0
- angr/state_plugins/scratch.py +173 -0
- angr/state_plugins/sim_action.py +326 -0
- angr/state_plugins/sim_action_object.py +271 -0
- angr/state_plugins/sim_event.py +59 -0
- angr/state_plugins/solver.py +1128 -0
- angr/state_plugins/symbolizer.py +291 -0
- angr/state_plugins/trace_additions.py +738 -0
- angr/state_plugins/uc_manager.py +94 -0
- angr/state_plugins/unicorn_engine.py +1920 -0
- angr/state_plugins/view.py +340 -0
- angr/storage/__init__.py +15 -0
- angr/storage/file.py +1210 -0
- angr/storage/memory_mixins/__init__.py +317 -0
- angr/storage/memory_mixins/actions_mixin.py +72 -0
- angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
- angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
- angr/storage/memory_mixins/clouseau_mixin.py +137 -0
- angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
- angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
- angr/storage/memory_mixins/default_filler_mixin.py +144 -0
- angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
- angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
- angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
- angr/storage/memory_mixins/keyvalue_memory_mixin.py +43 -0
- angr/storage/memory_mixins/label_merger_mixin.py +31 -0
- angr/storage/memory_mixins/memory_mixin.py +175 -0
- angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
- angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
- angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
- angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
- angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
- angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +529 -0
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
- angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
- angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
- angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +442 -0
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
- angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
- angr/storage/memory_mixins/simplification_mixin.py +15 -0
- angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
- angr/storage/memory_mixins/slotted_memory.py +140 -0
- angr/storage/memory_mixins/smart_find_mixin.py +161 -0
- angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
- angr/storage/memory_mixins/top_merger_mixin.py +25 -0
- angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
- angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
- angr/storage/memory_object.py +195 -0
- angr/tablespecs.py +91 -0
- angr/unicornlib.dylib +0 -0
- angr/utils/__init__.py +46 -0
- angr/utils/ail.py +176 -0
- angr/utils/algo.py +34 -0
- angr/utils/balancer.py +776 -0
- angr/utils/bits.py +46 -0
- angr/utils/constants.py +9 -0
- angr/utils/cowdict.py +63 -0
- angr/utils/cpp.py +17 -0
- angr/utils/doms.py +150 -0
- angr/utils/dynamic_dictlist.py +89 -0
- angr/utils/endness.py +18 -0
- angr/utils/enums_conv.py +97 -0
- angr/utils/env.py +12 -0
- angr/utils/formatting.py +128 -0
- angr/utils/funcid.py +244 -0
- angr/utils/graph.py +981 -0
- angr/utils/lazy_import.py +13 -0
- angr/utils/library.py +236 -0
- angr/utils/loader.py +55 -0
- angr/utils/mp.py +66 -0
- angr/utils/orderedset.py +74 -0
- angr/utils/ssa/__init__.py +455 -0
- angr/utils/ssa/tmp_uses_collector.py +23 -0
- angr/utils/ssa/vvar_uses_collector.py +36 -0
- angr/utils/strings.py +20 -0
- angr/utils/tagged_interval_map.py +112 -0
- angr/utils/timing.py +74 -0
- angr/utils/types.py +193 -0
- angr/utils/vex.py +11 -0
- angr/vaults.py +367 -0
- angr-9.2.192.dist-info/METADATA +112 -0
- angr-9.2.192.dist-info/RECORD +1442 -0
- angr-9.2.192.dist-info/WHEEL +6 -0
- angr-9.2.192.dist-info/entry_points.txt +2 -0
- angr-9.2.192.dist-info/licenses/LICENSE +27 -0
- angr-9.2.192.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2009 @@
|
|
|
1
|
+
# pylint:disable=missing-class-docstring,too-many-boolean-expressions
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import enum
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
import networkx
|
|
9
|
+
from sortedcontainers import SortedDict
|
|
10
|
+
|
|
11
|
+
from angr.utils.constants import MAX_POINTSTO_BITS
|
|
12
|
+
from .typevars import (
|
|
13
|
+
Existence,
|
|
14
|
+
Subtype,
|
|
15
|
+
Equivalence,
|
|
16
|
+
Add,
|
|
17
|
+
Sub,
|
|
18
|
+
TypeVariable,
|
|
19
|
+
DerivedTypeVariable,
|
|
20
|
+
HasField,
|
|
21
|
+
AddN,
|
|
22
|
+
SubN,
|
|
23
|
+
IsArray,
|
|
24
|
+
TypeConstraint,
|
|
25
|
+
Load,
|
|
26
|
+
Store,
|
|
27
|
+
BaseLabel,
|
|
28
|
+
FuncIn,
|
|
29
|
+
FuncOut,
|
|
30
|
+
ConvertTo,
|
|
31
|
+
new_dtv,
|
|
32
|
+
)
|
|
33
|
+
from .typeconsts import (
|
|
34
|
+
BottomType,
|
|
35
|
+
TopType,
|
|
36
|
+
TypeConstant,
|
|
37
|
+
Int,
|
|
38
|
+
Int8,
|
|
39
|
+
Int16,
|
|
40
|
+
Int32,
|
|
41
|
+
Int64,
|
|
42
|
+
Int128,
|
|
43
|
+
Int256,
|
|
44
|
+
Int512,
|
|
45
|
+
Pointer,
|
|
46
|
+
Pointer32,
|
|
47
|
+
Pointer64,
|
|
48
|
+
Struct,
|
|
49
|
+
Array,
|
|
50
|
+
Function,
|
|
51
|
+
int_type,
|
|
52
|
+
Float,
|
|
53
|
+
Float32,
|
|
54
|
+
Float64,
|
|
55
|
+
)
|
|
56
|
+
from .variance import Variance
|
|
57
|
+
from .dfa import DFAConstraintSolver, EmptyEpsilonNFAError
|
|
58
|
+
|
|
59
|
+
_l = logging.getLogger(__name__)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
Top_ = TopType()
|
|
63
|
+
Int_ = Int()
|
|
64
|
+
Int512_ = Int512()
|
|
65
|
+
Int256_ = Int256()
|
|
66
|
+
Int128_ = Int128()
|
|
67
|
+
Int64_ = Int64()
|
|
68
|
+
Int32_ = Int32()
|
|
69
|
+
Int16_ = Int16()
|
|
70
|
+
Int8_ = Int8()
|
|
71
|
+
Bottom_ = BottomType()
|
|
72
|
+
Pointer64_ = Pointer64()
|
|
73
|
+
Pointer32_ = Pointer32()
|
|
74
|
+
Struct_ = Struct()
|
|
75
|
+
Array_ = Array()
|
|
76
|
+
Float_ = Float()
|
|
77
|
+
Float32_ = Float32()
|
|
78
|
+
Float64_ = Float64()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
PRIMITIVE_TYPES = {
|
|
82
|
+
Top_,
|
|
83
|
+
Int_,
|
|
84
|
+
Int8_,
|
|
85
|
+
Int16_,
|
|
86
|
+
Int32_,
|
|
87
|
+
Int64_,
|
|
88
|
+
Int128_,
|
|
89
|
+
Int256_,
|
|
90
|
+
Int512_,
|
|
91
|
+
Pointer32_,
|
|
92
|
+
Pointer64_,
|
|
93
|
+
Bottom_,
|
|
94
|
+
Struct_,
|
|
95
|
+
Array_,
|
|
96
|
+
Float_,
|
|
97
|
+
Float32_,
|
|
98
|
+
Float64_,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# lattice for 64-bit binaries
|
|
103
|
+
BASE_LATTICE_64 = networkx.DiGraph()
|
|
104
|
+
BASE_LATTICE_64.add_edge(Top_, Int_)
|
|
105
|
+
BASE_LATTICE_64.add_edge(Int_, Int512_)
|
|
106
|
+
BASE_LATTICE_64.add_edge(Int_, Int256_)
|
|
107
|
+
BASE_LATTICE_64.add_edge(Int_, Int128_)
|
|
108
|
+
BASE_LATTICE_64.add_edge(Int_, Int64_)
|
|
109
|
+
BASE_LATTICE_64.add_edge(Int_, Int32_)
|
|
110
|
+
BASE_LATTICE_64.add_edge(Int_, Int16_)
|
|
111
|
+
BASE_LATTICE_64.add_edge(Int_, Int8_)
|
|
112
|
+
BASE_LATTICE_64.add_edge(Int32_, Bottom_)
|
|
113
|
+
BASE_LATTICE_64.add_edge(Int16_, Bottom_)
|
|
114
|
+
BASE_LATTICE_64.add_edge(Int8_, Bottom_)
|
|
115
|
+
BASE_LATTICE_64.add_edge(Int64_, Pointer64_)
|
|
116
|
+
BASE_LATTICE_64.add_edge(Pointer64_, Bottom_)
|
|
117
|
+
|
|
118
|
+
# lattice for 32-bit binaries
|
|
119
|
+
BASE_LATTICE_32 = networkx.DiGraph()
|
|
120
|
+
BASE_LATTICE_32.add_edge(Top_, Int_)
|
|
121
|
+
BASE_LATTICE_32.add_edge(Int_, Int512_)
|
|
122
|
+
BASE_LATTICE_32.add_edge(Int_, Int256_)
|
|
123
|
+
BASE_LATTICE_32.add_edge(Int_, Int128_)
|
|
124
|
+
BASE_LATTICE_32.add_edge(Int_, Int64_)
|
|
125
|
+
BASE_LATTICE_32.add_edge(Int_, Int32_)
|
|
126
|
+
BASE_LATTICE_32.add_edge(Int_, Int16_)
|
|
127
|
+
BASE_LATTICE_32.add_edge(Int_, Int8_)
|
|
128
|
+
BASE_LATTICE_32.add_edge(Int32_, Pointer32_)
|
|
129
|
+
BASE_LATTICE_32.add_edge(Int64_, Bottom_)
|
|
130
|
+
BASE_LATTICE_32.add_edge(Pointer32_, Bottom_)
|
|
131
|
+
BASE_LATTICE_32.add_edge(Int16_, Bottom_)
|
|
132
|
+
BASE_LATTICE_32.add_edge(Int8_, Bottom_)
|
|
133
|
+
|
|
134
|
+
BASE_LATTICES = {
|
|
135
|
+
32: BASE_LATTICE_32,
|
|
136
|
+
64: BASE_LATTICE_64,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
#
|
|
141
|
+
# Sketch
|
|
142
|
+
#
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class SketchNodeBase:
|
|
146
|
+
"""
|
|
147
|
+
The base class for nodes in a sketch.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
__slots__ = ()
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class SketchNode(SketchNodeBase):
|
|
154
|
+
"""
|
|
155
|
+
Represents a node in a sketch graph.
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
__slots__ = ("lower_bound", "typevar", "upper_bound")
|
|
159
|
+
|
|
160
|
+
def __init__(self, typevar: TypeVariable | DerivedTypeVariable):
|
|
161
|
+
self.typevar: TypeVariable | DerivedTypeVariable = typevar
|
|
162
|
+
self.upper_bound: TypeConstant = TopType()
|
|
163
|
+
self.lower_bound: TypeConstant = BottomType()
|
|
164
|
+
|
|
165
|
+
def __repr__(self):
|
|
166
|
+
return f"{self.lower_bound} <: {self.typevar} <: {self.upper_bound}"
|
|
167
|
+
|
|
168
|
+
def __eq__(self, other):
|
|
169
|
+
return isinstance(other, SketchNode) and self.typevar == other.typevar
|
|
170
|
+
|
|
171
|
+
def __hash__(self):
|
|
172
|
+
return hash((SketchNode, self.typevar))
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def size(self) -> int | None:
|
|
176
|
+
"""
|
|
177
|
+
Best-effort estimation of the size of the typevar (in bits). Returns None if we cannot determine.
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
if isinstance(self.typevar, DerivedTypeVariable):
|
|
181
|
+
last_label = self.typevar.labels[-1]
|
|
182
|
+
if isinstance(last_label, HasField) and last_label.bits != MAX_POINTSTO_BITS:
|
|
183
|
+
return last_label.bits
|
|
184
|
+
if isinstance(self.lower_bound, TypeConstant) and not isinstance(self.lower_bound, (TopType, BottomType)):
|
|
185
|
+
with suppress(NotImplementedError):
|
|
186
|
+
return self.lower_bound.size * 8
|
|
187
|
+
if isinstance(self.upper_bound, TypeConstant) and not isinstance(self.upper_bound, (TopType, BottomType)):
|
|
188
|
+
with suppress(NotImplementedError):
|
|
189
|
+
return self.upper_bound.size * 8
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class RecursiveRefNode(SketchNodeBase):
|
|
194
|
+
"""
|
|
195
|
+
Represents a cycle in a sketch graph.
|
|
196
|
+
|
|
197
|
+
This is equivalent to sketches.LabelNode in the reference implementation of retypd.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
def __init__(self, target: TypeVariable | DerivedTypeVariable):
|
|
201
|
+
self.target: TypeVariable | DerivedTypeVariable = target
|
|
202
|
+
|
|
203
|
+
def __repr__(self):
|
|
204
|
+
return f"Ref({self.target})"
|
|
205
|
+
|
|
206
|
+
def __hash__(self):
|
|
207
|
+
return hash((RecursiveRefNode, self.target))
|
|
208
|
+
|
|
209
|
+
def __eq__(self, other):
|
|
210
|
+
return type(other) is RecursiveRefNode and other.target == self.target
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class Sketch:
|
|
214
|
+
"""
|
|
215
|
+
Describes the sketch of a type variable.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
__slots__ = (
|
|
219
|
+
"graph",
|
|
220
|
+
"node_mapping",
|
|
221
|
+
"root",
|
|
222
|
+
"solver",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
def __init__(self, solver: SimpleSolver, root: TypeVariable):
|
|
226
|
+
self.root: SketchNode = SketchNode(root)
|
|
227
|
+
self.graph = networkx.MultiDiGraph()
|
|
228
|
+
self.node_mapping: dict[TypeVariable | DerivedTypeVariable, SketchNodeBase] = {}
|
|
229
|
+
self.solver = solver
|
|
230
|
+
|
|
231
|
+
# add the root node
|
|
232
|
+
self.graph.add_node(self.root)
|
|
233
|
+
self.node_mapping[root] = self.root
|
|
234
|
+
|
|
235
|
+
def lookup(self, typevar: TypeVariable | DerivedTypeVariable) -> SketchNodeBase | None:
|
|
236
|
+
if typevar in self.node_mapping:
|
|
237
|
+
return self.node_mapping[typevar]
|
|
238
|
+
node: SketchNodeBase | None = None
|
|
239
|
+
if isinstance(typevar, DerivedTypeVariable):
|
|
240
|
+
t = SimpleSolver._to_typevar_or_typeconst(typevar.type_var)
|
|
241
|
+
assert isinstance(t, TypeVariable)
|
|
242
|
+
node = self.node_mapping[t]
|
|
243
|
+
for label in typevar.labels:
|
|
244
|
+
succs = []
|
|
245
|
+
for _, dst, data in self.graph.out_edges(node, data=True):
|
|
246
|
+
if "label" in data and data["label"] == label and dst not in succs:
|
|
247
|
+
succs.append(dst)
|
|
248
|
+
if len(succs) > 1:
|
|
249
|
+
_l.warning(
|
|
250
|
+
"Multiple successors found for node %s with label %s. Picking the first one.", node, label
|
|
251
|
+
)
|
|
252
|
+
succs = succs[:1]
|
|
253
|
+
if not succs:
|
|
254
|
+
return None
|
|
255
|
+
node = succs[0]
|
|
256
|
+
if isinstance(node, RecursiveRefNode):
|
|
257
|
+
node = self.lookup(node.target)
|
|
258
|
+
return node
|
|
259
|
+
|
|
260
|
+
def add_edge(self, src: SketchNodeBase, dst: SketchNodeBase, label) -> None:
|
|
261
|
+
# ensure the label does not already exist in existing edges
|
|
262
|
+
if self.graph.has_edge(src, dst):
|
|
263
|
+
for data in self.graph.get_edge_data(src, dst).values():
|
|
264
|
+
if "label" in data and data["label"] == label:
|
|
265
|
+
return
|
|
266
|
+
if isinstance(src, SketchNode) and src.typevar not in self.node_mapping:
|
|
267
|
+
self.node_mapping[src.typevar] = src
|
|
268
|
+
if isinstance(dst, SketchNode) and dst.typevar not in self.node_mapping:
|
|
269
|
+
self.node_mapping[dst.typevar] = dst
|
|
270
|
+
self.graph.add_edge(src, dst, label=label)
|
|
271
|
+
|
|
272
|
+
def add_constraint(self, constraint: TypeConstraint) -> None:
|
|
273
|
+
# sub <: super
|
|
274
|
+
if not isinstance(constraint, Subtype):
|
|
275
|
+
return
|
|
276
|
+
subtype, _ = self.flatten_typevar(constraint.sub_type)
|
|
277
|
+
supertype, try_maxsize = self.flatten_typevar(constraint.super_type)
|
|
278
|
+
|
|
279
|
+
if (
|
|
280
|
+
try_maxsize
|
|
281
|
+
and isinstance(subtype, TypeVariable)
|
|
282
|
+
and subtype in self.solver.stackvar_max_sizes
|
|
283
|
+
and isinstance(supertype, TypeConstant)
|
|
284
|
+
and not isinstance(supertype, BottomType)
|
|
285
|
+
):
|
|
286
|
+
basetype = supertype
|
|
287
|
+
if not isinstance(basetype, (TopType, BottomType)):
|
|
288
|
+
assert basetype.size is not None
|
|
289
|
+
max_size = self.solver.stackvar_max_sizes.get(subtype, None)
|
|
290
|
+
if max_size not in {0, None} and basetype.size > 0 and max_size // basetype.size > 0: # type: ignore
|
|
291
|
+
supertype = Array(element=basetype, count=max_size // basetype.size) # type: ignore
|
|
292
|
+
|
|
293
|
+
if SimpleSolver._typevar_inside_set(subtype, PRIMITIVE_TYPES) and not SimpleSolver._typevar_inside_set(
|
|
294
|
+
supertype, PRIMITIVE_TYPES
|
|
295
|
+
):
|
|
296
|
+
assert isinstance(supertype, (TypeVariable, DerivedTypeVariable))
|
|
297
|
+
super_node = self.lookup(supertype)
|
|
298
|
+
assert super_node is None or isinstance(super_node, SketchNode)
|
|
299
|
+
if super_node is not None:
|
|
300
|
+
super_node.lower_bound = self.solver.join(super_node.lower_bound, subtype)
|
|
301
|
+
elif SimpleSolver._typevar_inside_set(supertype, PRIMITIVE_TYPES) and not SimpleSolver._typevar_inside_set(
|
|
302
|
+
subtype, PRIMITIVE_TYPES
|
|
303
|
+
):
|
|
304
|
+
assert isinstance(subtype, (TypeVariable, DerivedTypeVariable))
|
|
305
|
+
sub_node = self.lookup(subtype)
|
|
306
|
+
assert sub_node is None or isinstance(sub_node, SketchNode)
|
|
307
|
+
# assert sub_node is not None
|
|
308
|
+
if sub_node is not None:
|
|
309
|
+
sub_node.upper_bound = self.solver.meet(sub_node.upper_bound, supertype)
|
|
310
|
+
|
|
311
|
+
@staticmethod
|
|
312
|
+
def flatten_typevar(
|
|
313
|
+
derived_typevar: TypeVariable | TypeConstant | DerivedTypeVariable,
|
|
314
|
+
) -> tuple[DerivedTypeVariable | TypeVariable | TypeConstant, bool]:
|
|
315
|
+
# pylint:disable=too-many-boolean-expressions
|
|
316
|
+
if (
|
|
317
|
+
isinstance(derived_typevar, DerivedTypeVariable)
|
|
318
|
+
and isinstance(derived_typevar.type_var, Pointer)
|
|
319
|
+
and SimpleSolver._typevar_inside_set(derived_typevar.type_var.basetype, PRIMITIVE_TYPES)
|
|
320
|
+
and len(derived_typevar.labels) == 2
|
|
321
|
+
and isinstance(derived_typevar.labels[0], Load)
|
|
322
|
+
and isinstance(derived_typevar.labels[1], HasField)
|
|
323
|
+
and derived_typevar.labels[1].offset == 0
|
|
324
|
+
and derived_typevar.labels[1].bits == MAX_POINTSTO_BITS
|
|
325
|
+
):
|
|
326
|
+
bt = derived_typevar.type_var.basetype
|
|
327
|
+
assert bt is not None
|
|
328
|
+
return bt, True
|
|
329
|
+
return derived_typevar, False
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
#
|
|
333
|
+
# Constraint graph
|
|
334
|
+
#
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
class ConstraintGraphTag(enum.Enum):
|
|
338
|
+
LEFT = 0
|
|
339
|
+
RIGHT = 1
|
|
340
|
+
UNKNOWN = 2
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
class FORGOTTEN(enum.Enum):
|
|
344
|
+
PRE_FORGOTTEN = 0
|
|
345
|
+
POST_FORGOTTEN = 1
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
class ConstraintGraphNode:
|
|
349
|
+
__slots__ = ("forgotten", "tag", "typevar", "variance")
|
|
350
|
+
|
|
351
|
+
def __init__(
|
|
352
|
+
self,
|
|
353
|
+
typevar: TypeVariable | DerivedTypeVariable | TypeConstant,
|
|
354
|
+
variance: Variance,
|
|
355
|
+
tag: ConstraintGraphTag,
|
|
356
|
+
forgotten: FORGOTTEN,
|
|
357
|
+
):
|
|
358
|
+
self.typevar = typevar
|
|
359
|
+
self.variance = variance
|
|
360
|
+
self.tag = tag
|
|
361
|
+
self.forgotten = forgotten
|
|
362
|
+
|
|
363
|
+
def __repr__(self):
|
|
364
|
+
variance_str = "CO" if self.variance == Variance.COVARIANT else "CONTRA"
|
|
365
|
+
if self.tag == ConstraintGraphTag.LEFT:
|
|
366
|
+
tag_str = "L"
|
|
367
|
+
elif self.tag == ConstraintGraphTag.RIGHT:
|
|
368
|
+
tag_str = "R"
|
|
369
|
+
else:
|
|
370
|
+
tag_str = "U"
|
|
371
|
+
forgotten_str = "PRE" if self.forgotten == FORGOTTEN.PRE_FORGOTTEN else "POST"
|
|
372
|
+
s = f"{self.typevar}#{variance_str}.{tag_str}.{forgotten_str}"
|
|
373
|
+
if ":" in s:
|
|
374
|
+
return '"' + s + '"'
|
|
375
|
+
return s
|
|
376
|
+
|
|
377
|
+
def __eq__(self, other):
|
|
378
|
+
if not isinstance(other, ConstraintGraphNode):
|
|
379
|
+
return False
|
|
380
|
+
return (
|
|
381
|
+
self.typevar == other.typevar
|
|
382
|
+
and self.variance == other.variance
|
|
383
|
+
and self.tag == other.tag
|
|
384
|
+
and self.forgotten == other.forgotten
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
def __hash__(self):
|
|
388
|
+
return hash((ConstraintGraphNode, self.typevar, self.variance, self.tag, self.forgotten))
|
|
389
|
+
|
|
390
|
+
def forget_last_label(self) -> tuple[ConstraintGraphNode, BaseLabel] | None:
|
|
391
|
+
if isinstance(self.typevar, DerivedTypeVariable) and self.typevar.labels:
|
|
392
|
+
last_label = self.typevar.labels[-1]
|
|
393
|
+
if len(self.typevar.labels) == 1:
|
|
394
|
+
prefix = self.typevar.type_var
|
|
395
|
+
else:
|
|
396
|
+
prefix = DerivedTypeVariable(self.typevar.type_var, None, labels=self.typevar.labels[:-1])
|
|
397
|
+
variance = Variance.COVARIANT if self.variance == last_label.variance else Variance.CONTRAVARIANT
|
|
398
|
+
if not isinstance(prefix, (TypeVariable, DerivedTypeVariable)):
|
|
399
|
+
# we may see incorrectly generated type constraints that attempt to load from an int:
|
|
400
|
+
# int64.load
|
|
401
|
+
# we don't want to entertain such constraints
|
|
402
|
+
return None
|
|
403
|
+
return (
|
|
404
|
+
ConstraintGraphNode(prefix, variance, self.tag, FORGOTTEN.PRE_FORGOTTEN),
|
|
405
|
+
self.typevar.labels[-1],
|
|
406
|
+
)
|
|
407
|
+
return None
|
|
408
|
+
|
|
409
|
+
def recall(self, label: BaseLabel) -> ConstraintGraphNode:
|
|
410
|
+
if isinstance(self.typevar, DerivedTypeVariable):
|
|
411
|
+
labels = (*self.typevar.labels, label)
|
|
412
|
+
typevar = self.typevar.type_var
|
|
413
|
+
elif isinstance(self.typevar, (TypeVariable, TypeConstant)):
|
|
414
|
+
labels = (label,)
|
|
415
|
+
typevar = self.typevar
|
|
416
|
+
else:
|
|
417
|
+
raise TypeError(f"Unsupported type {type(self.typevar)}")
|
|
418
|
+
variance = Variance.COVARIANT if self.variance == label.variance else Variance.CONTRAVARIANT
|
|
419
|
+
var = typevar if not labels else DerivedTypeVariable(typevar, None, labels=labels)
|
|
420
|
+
assert isinstance(var, (TypeVariable, DerivedTypeVariable))
|
|
421
|
+
return ConstraintGraphNode(var, variance, self.tag, FORGOTTEN.PRE_FORGOTTEN)
|
|
422
|
+
|
|
423
|
+
def inverse(self) -> ConstraintGraphNode:
|
|
424
|
+
if self.tag == ConstraintGraphTag.LEFT:
|
|
425
|
+
tag = ConstraintGraphTag.RIGHT
|
|
426
|
+
elif self.tag == ConstraintGraphTag.RIGHT:
|
|
427
|
+
tag = ConstraintGraphTag.LEFT
|
|
428
|
+
else:
|
|
429
|
+
tag = ConstraintGraphTag.UNKNOWN
|
|
430
|
+
|
|
431
|
+
variance = Variance.CONTRAVARIANT if self.variance == Variance.COVARIANT else Variance.COVARIANT
|
|
432
|
+
|
|
433
|
+
return ConstraintGraphNode(self.typevar, variance, tag, self.forgotten)
|
|
434
|
+
|
|
435
|
+
def inverse_wo_tag(self) -> ConstraintGraphNode:
|
|
436
|
+
"""
|
|
437
|
+
Invert the variance only.
|
|
438
|
+
"""
|
|
439
|
+
variance = Variance.CONTRAVARIANT if self.variance == Variance.COVARIANT else Variance.COVARIANT
|
|
440
|
+
|
|
441
|
+
return ConstraintGraphNode(self.typevar, variance, self.tag, self.forgotten)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
#
|
|
445
|
+
# The solver
|
|
446
|
+
#
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
class SimpleSolver:
|
|
450
|
+
"""
|
|
451
|
+
SimpleSolver is, by its name, a simple solver. Most of this solver is based on the (complex) simplification logic
|
|
452
|
+
that the retypd paper describes and the retypd re-implementation (https://github.com/GrammaTech/retypd) implements.
|
|
453
|
+
Additionally, we add some improvements to allow type propagation of known struct names, among a few other
|
|
454
|
+
improvements.
|
|
455
|
+
"""
|
|
456
|
+
|
|
457
|
+
def __init__(
|
|
458
|
+
self,
|
|
459
|
+
bits: int,
|
|
460
|
+
constraints,
|
|
461
|
+
typevars: dict[TypeVariable, set[TypeVariable]],
|
|
462
|
+
constraint_set_degradation_threshold: int = 150,
|
|
463
|
+
stackvar_max_sizes: dict[TypeVariable, int] | None = None,
|
|
464
|
+
):
|
|
465
|
+
if bits not in (32, 64):
|
|
466
|
+
raise ValueError(f"Pointer size {bits} is not supported. Expect 32 or 64.")
|
|
467
|
+
|
|
468
|
+
self.bits = bits
|
|
469
|
+
self._constraints: dict[TypeVariable, set[TypeConstraint]] = constraints
|
|
470
|
+
self._typevars: dict[TypeVariable, set[TypeVariable]] = typevars
|
|
471
|
+
self.stackvar_max_sizes = stackvar_max_sizes if stackvar_max_sizes is not None else {}
|
|
472
|
+
self._constraint_set_degradation_threshold = constraint_set_degradation_threshold
|
|
473
|
+
self._base_lattice = BASE_LATTICES[bits]
|
|
474
|
+
self._base_lattice_inverted = networkx.DiGraph()
|
|
475
|
+
for src, dst in self._base_lattice.edges:
|
|
476
|
+
self._base_lattice_inverted.add_edge(dst, src)
|
|
477
|
+
|
|
478
|
+
# statistics
|
|
479
|
+
self.processed_constraints_count: int = 0
|
|
480
|
+
self.simplified_constraints_count: int = 0
|
|
481
|
+
self.eqclass_constraints_count: list[int] = []
|
|
482
|
+
|
|
483
|
+
#
|
|
484
|
+
# Solving state
|
|
485
|
+
#
|
|
486
|
+
self._equivalence = defaultdict(dict)
|
|
487
|
+
for func_tv in list(self._constraints):
|
|
488
|
+
if self._constraints[func_tv]:
|
|
489
|
+
self.processed_constraints_count += len(self._constraints[func_tv])
|
|
490
|
+
self.preprocess(func_tv)
|
|
491
|
+
self.simplified_constraints_count += len(self._constraints[func_tv])
|
|
492
|
+
|
|
493
|
+
self.solution = {}
|
|
494
|
+
for tv, sol in self._equivalence.items():
|
|
495
|
+
if isinstance(tv, TypeVariable) and isinstance(sol, TypeConstant):
|
|
496
|
+
self.solution[tv] = sol
|
|
497
|
+
|
|
498
|
+
self._solution_cache = {}
|
|
499
|
+
self.solve()
|
|
500
|
+
for func_tv in list(self._constraints):
|
|
501
|
+
self._convert_arrays(self._constraints[func_tv])
|
|
502
|
+
|
|
503
|
+
def preprocess(self, func_tv: TypeVariable):
|
|
504
|
+
self._constraints[func_tv] |= self._eq_constraints_from_tvs(self._constraints[func_tv])
|
|
505
|
+
ptr_tvs = self._ptr_tvs_from_constraints(self._constraints[func_tv])
|
|
506
|
+
self._constraints[func_tv] = self._remove_alignment_int_ptr_subtyping_constraints(
|
|
507
|
+
self._constraints[func_tv], ptr_tvs
|
|
508
|
+
)
|
|
509
|
+
self._constraints[func_tv] |= self._eq_constraints_from_add(func_tv, ptr_tvs)
|
|
510
|
+
self._constraints[func_tv] |= self._eq_constraints_from_sub(func_tv, ptr_tvs)
|
|
511
|
+
self._constraints[func_tv] |= self._discover_equivalence(self._constraints[func_tv])
|
|
512
|
+
new_constraints, replacements = self._handle_equivalence(self._constraints[func_tv])
|
|
513
|
+
self._equivalence |= replacements
|
|
514
|
+
self._constraints[func_tv] = new_constraints
|
|
515
|
+
self._constraints[func_tv] = self._filter_constraints(self._constraints[func_tv])
|
|
516
|
+
|
|
517
|
+
def solve(self):
|
|
518
|
+
"""
|
|
519
|
+
Steps:
|
|
520
|
+
|
|
521
|
+
For each type variable,
|
|
522
|
+
- Infer the shape in its sketch
|
|
523
|
+
- Build the constraint graph
|
|
524
|
+
- Collect all constraints
|
|
525
|
+
- Apply constraints to derive the lower and upper bounds
|
|
526
|
+
- Determine a solution for type variables with constraints
|
|
527
|
+
- Rewrite the constraint graph by replacing determined type variables with their solutions
|
|
528
|
+
- Solve repeatedly until all interesting type variables have solutions
|
|
529
|
+
|
|
530
|
+
By repeatedly solving until exhausting interesting type variables, we ensure the S-Trans rule is applied.
|
|
531
|
+
"""
|
|
532
|
+
|
|
533
|
+
prem_typevars = set(self._constraints) | next(iter(self._typevars.values()))
|
|
534
|
+
typevars = set()
|
|
535
|
+
for tv in prem_typevars:
|
|
536
|
+
if tv not in self._equivalence:
|
|
537
|
+
typevars.add(tv)
|
|
538
|
+
else:
|
|
539
|
+
repl = self._equivalence[tv]
|
|
540
|
+
if isinstance(repl, TypeVariable):
|
|
541
|
+
typevars.add(repl)
|
|
542
|
+
|
|
543
|
+
constraints = set()
|
|
544
|
+
|
|
545
|
+
for tv in typevars:
|
|
546
|
+
if tv in self._constraints:
|
|
547
|
+
constraints |= self._constraints[tv]
|
|
548
|
+
|
|
549
|
+
equiv_classes, prelim_sketches = self.infer_shapes(typevars, constraints)
|
|
550
|
+
|
|
551
|
+
# only create sketches for the type variables representing their equivalence classes
|
|
552
|
+
tv_to_reptvs = {}
|
|
553
|
+
for tv_or_dtv, reptv in equiv_classes.items():
|
|
554
|
+
if not isinstance(tv_or_dtv, DerivedTypeVariable) and tv_or_dtv is not reptv:
|
|
555
|
+
tv_to_reptvs[tv_or_dtv] = reptv
|
|
556
|
+
# rewrite constraints to only use representative type variables
|
|
557
|
+
constraints = self._rewrite_constraints_with_replacements(constraints, tv_to_reptvs)
|
|
558
|
+
# update sketches
|
|
559
|
+
sketches = {tv_to_reptvs.get(tv, tv): sketch for tv, sketch in prelim_sketches.items()}
|
|
560
|
+
# rewrite typevars as well...
|
|
561
|
+
typevars = {tv_to_reptvs.get(tv, tv) for tv in typevars}
|
|
562
|
+
|
|
563
|
+
# collect typevars used in the constraint set
|
|
564
|
+
constrained_typevars = set()
|
|
565
|
+
for constraint in constraints:
|
|
566
|
+
if isinstance(constraint, Subtype):
|
|
567
|
+
for t in (constraint.sub_type, constraint.super_type):
|
|
568
|
+
if isinstance(t, DerivedTypeVariable):
|
|
569
|
+
if t.type_var in typevars:
|
|
570
|
+
constrained_typevars.add(t.type_var)
|
|
571
|
+
elif isinstance(t, TypeVariable) and t in typevars:
|
|
572
|
+
constrained_typevars.add(t)
|
|
573
|
+
|
|
574
|
+
constraintset2tvs = defaultdict(set)
|
|
575
|
+
tvs_seen = set()
|
|
576
|
+
for idx, tv in enumerate(sorted(constrained_typevars, key=lambda x: x.idx)):
|
|
577
|
+
_l.debug("Collecting constraints for type variable %r (%d/%d)", tv, idx + 1, len(constrained_typevars))
|
|
578
|
+
if tv in tvs_seen:
|
|
579
|
+
continue
|
|
580
|
+
# build a sub constraint set for the type variable
|
|
581
|
+
constraint_subset, related_tvs = self._generate_constraint_subset(constraints, {tv})
|
|
582
|
+
# drop all type vars outside constrained_typevars
|
|
583
|
+
related_tvs = related_tvs.intersection(constrained_typevars)
|
|
584
|
+
tvs_seen |= related_tvs
|
|
585
|
+
frozen_constraint_subset = frozenset(constraint_subset)
|
|
586
|
+
constraintset2tvs[frozen_constraint_subset] = related_tvs
|
|
587
|
+
|
|
588
|
+
for idx, (constraint_subset, tvs) in enumerate(constraintset2tvs.items()):
|
|
589
|
+
_l.debug(
|
|
590
|
+
"Solving %d constraints for %d type variables %r (%d/%d)",
|
|
591
|
+
len(constraint_subset),
|
|
592
|
+
len(tvs),
|
|
593
|
+
tvs,
|
|
594
|
+
idx + 1,
|
|
595
|
+
len(constraintset2tvs),
|
|
596
|
+
)
|
|
597
|
+
self.eqclass_constraints_count.append(len(constraint_subset))
|
|
598
|
+
|
|
599
|
+
constraint_subset = self._drop_missized_constraints(tvs, constraint_subset)
|
|
600
|
+
|
|
601
|
+
if len(constraint_subset) > self._constraint_set_degradation_threshold:
|
|
602
|
+
_l.debug(
|
|
603
|
+
"Constraint subset contains %d constraints, which is over the limit of %d. Enter degradation.",
|
|
604
|
+
len(constraint_subset),
|
|
605
|
+
self._constraint_set_degradation_threshold,
|
|
606
|
+
)
|
|
607
|
+
constraint_subset = self._degrade_constraint_set(constraint_subset)
|
|
608
|
+
_l.debug("Degraded constraint subset to %d constraints.", len(constraint_subset))
|
|
609
|
+
|
|
610
|
+
while constraint_subset:
|
|
611
|
+
|
|
612
|
+
_l.debug("Working with %d constraints.", len(constraint_subset))
|
|
613
|
+
|
|
614
|
+
# remove constraints that are a <: b where a only appears once; in this case, the solution fo a is
|
|
615
|
+
# entirely determined by the solution of b (which is the upper bound of a)
|
|
616
|
+
filtered_constraint_subset, ub_subtypes = self._filter_leaf_typevars(constraint_subset, tvs)
|
|
617
|
+
_l.debug(
|
|
618
|
+
"Filtered %d leaf typevars; %d constraints remain.",
|
|
619
|
+
len(ub_subtypes),
|
|
620
|
+
len(filtered_constraint_subset),
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
base_constraint_graph = self._generate_constraint_graph(
|
|
624
|
+
filtered_constraint_subset, tvs | PRIMITIVE_TYPES
|
|
625
|
+
)
|
|
626
|
+
primitive_constraints = self._generate_primitive_constraints(tvs, base_constraint_graph)
|
|
627
|
+
if len(tvs) > 1:
|
|
628
|
+
primitive_constraints |= self._generate_transitive_subtype_constraints(
|
|
629
|
+
tvs, filtered_constraint_subset, primitive_constraints
|
|
630
|
+
)
|
|
631
|
+
tvs_with_primitive_constraints = set()
|
|
632
|
+
for primitive_constraint in primitive_constraints:
|
|
633
|
+
tv = self._typevar_from_primitive_constraint(primitive_constraint)
|
|
634
|
+
tvs_with_primitive_constraints.add(tv)
|
|
635
|
+
assert tv is not None, f"Cannot find type variable in primitive constraint {primitive_constraint}"
|
|
636
|
+
sketches[tv].add_constraint(primitive_constraint)
|
|
637
|
+
solutions = {}
|
|
638
|
+
self.determine(
|
|
639
|
+
sketches, sorted(tvs_with_primitive_constraints, key=lambda x: x.idx), equiv_classes, solutions
|
|
640
|
+
)
|
|
641
|
+
_l.debug("Determined solutions for %d type variable(s).", len(tvs_with_primitive_constraints))
|
|
642
|
+
|
|
643
|
+
leaf_solutions = 0
|
|
644
|
+
for tv_, ub_tv in ub_subtypes.items():
|
|
645
|
+
if ub_tv in solutions:
|
|
646
|
+
solutions[tv_] = solutions[ub_tv]
|
|
647
|
+
leaf_solutions += 1
|
|
648
|
+
elif isinstance(ub_tv, TypeConstant):
|
|
649
|
+
solutions[tv_] = ub_tv
|
|
650
|
+
leaf_solutions += 1
|
|
651
|
+
_l.debug("Determined solutions for %d leaf type variable(s).", leaf_solutions)
|
|
652
|
+
|
|
653
|
+
if not solutions:
|
|
654
|
+
break
|
|
655
|
+
self.solution |= solutions
|
|
656
|
+
|
|
657
|
+
tvs = {tv for tv in tvs if tv not in solutions}
|
|
658
|
+
if not tvs:
|
|
659
|
+
break
|
|
660
|
+
# rewrite existing constraints
|
|
661
|
+
new_constraint_subset = set()
|
|
662
|
+
for constraint in constraint_subset:
|
|
663
|
+
rewritten = self._rewrite_constraint(constraint, solutions)
|
|
664
|
+
new_constraint_subset.add(rewritten)
|
|
665
|
+
constraint_subset = self._filter_constraints(new_constraint_subset)
|
|
666
|
+
|
|
667
|
+
# set the solution for missing type vars to TOP
|
|
668
|
+
self.determine(sketches, set(sketches).difference(set(self.solution)), equiv_classes, self.solution)
|
|
669
|
+
|
|
670
|
+
# set solutions for non-representative type variables
|
|
671
|
+
for tv, reptv in equiv_classes.items():
|
|
672
|
+
if reptv in self.solution and tv not in self.solution:
|
|
673
|
+
self.solution[tv] = self.solution[reptv]
|
|
674
|
+
|
|
675
|
+
def infer_shapes(
|
|
676
|
+
self, typevars: set[TypeVariable], constraints: set[TypeConstraint]
|
|
677
|
+
) -> tuple[dict, dict[TypeVariable, Sketch]]:
|
|
678
|
+
"""
|
|
679
|
+
Computing sketches from constraint sets. Implements Algorithm E.1 in the retypd paper.
|
|
680
|
+
"""
|
|
681
|
+
|
|
682
|
+
equivalence_classes, quotient_graph = self.compute_quotient_graph(constraints)
|
|
683
|
+
|
|
684
|
+
sketches: dict[TypeVariable, Sketch] = {}
|
|
685
|
+
for tv in typevars:
|
|
686
|
+
rep_tv = equivalence_classes.get(tv, tv)
|
|
687
|
+
if rep_tv not in sketches:
|
|
688
|
+
sketches[rep_tv] = Sketch(self, rep_tv)
|
|
689
|
+
|
|
690
|
+
for tv, sketch in sketches.items():
|
|
691
|
+
sketch_node = sketch.lookup(tv)
|
|
692
|
+
graph_node = equivalence_classes.get(tv, None)
|
|
693
|
+
# assert graph_node is not None
|
|
694
|
+
if graph_node is None or sketch_node is None:
|
|
695
|
+
continue
|
|
696
|
+
assert isinstance(graph_node, TypeVariable)
|
|
697
|
+
assert isinstance(sketch_node, SketchNode)
|
|
698
|
+
visited = {graph_node: sketch_node}
|
|
699
|
+
self._get_all_paths(quotient_graph, sketch, graph_node, visited)
|
|
700
|
+
return equivalence_classes, sketches
|
|
701
|
+
|
|
702
|
+
def compute_quotient_graph(self, constraints: set[TypeConstraint]):
|
|
703
|
+
"""
|
|
704
|
+
Compute the quotient graph (the constraint graph modulo ~ in Algorithm E.1 in the retypd paper) with respect to
|
|
705
|
+
a given set of type constraints.
|
|
706
|
+
"""
|
|
707
|
+
|
|
708
|
+
g = networkx.DiGraph()
|
|
709
|
+
# collect all derived type variables
|
|
710
|
+
typevars = self._typevars_from_constraints(constraints)
|
|
711
|
+
g.add_nodes_from(typevars)
|
|
712
|
+
# add paths for each derived type variable into the graph
|
|
713
|
+
for tv in typevars:
|
|
714
|
+
last_node = tv
|
|
715
|
+
prefix = tv
|
|
716
|
+
while isinstance(prefix, DerivedTypeVariable) and prefix.labels:
|
|
717
|
+
assert isinstance(last_node, DerivedTypeVariable)
|
|
718
|
+
prefix = prefix.longest_prefix()
|
|
719
|
+
if prefix is None:
|
|
720
|
+
continue
|
|
721
|
+
g.add_edge(prefix, last_node, label=last_node.labels[-1])
|
|
722
|
+
last_node = prefix
|
|
723
|
+
|
|
724
|
+
# compute the constraint graph modulo ~
|
|
725
|
+
equivalence_classes = {node: node for node in g}
|
|
726
|
+
|
|
727
|
+
load = Load()
|
|
728
|
+
store = Store()
|
|
729
|
+
for node in g.nodes:
|
|
730
|
+
lbl_to_node = {}
|
|
731
|
+
for succ in g.successors(node):
|
|
732
|
+
lbl_to_node[succ.labels[-1]] = succ
|
|
733
|
+
if load in lbl_to_node and store in lbl_to_node:
|
|
734
|
+
self._unify(equivalence_classes, lbl_to_node[load], lbl_to_node[store], g)
|
|
735
|
+
|
|
736
|
+
for constraint in constraints:
|
|
737
|
+
if isinstance(constraint, Subtype):
|
|
738
|
+
if self._typevar_inside_set(constraint.super_type, PRIMITIVE_TYPES) or self._typevar_inside_set(
|
|
739
|
+
constraint.sub_type, PRIMITIVE_TYPES
|
|
740
|
+
):
|
|
741
|
+
continue
|
|
742
|
+
self._unify(equivalence_classes, constraint.super_type, constraint.sub_type, g)
|
|
743
|
+
|
|
744
|
+
out_graph = networkx.MultiDiGraph() # there can be multiple edges between two nodes, each edge is associated
|
|
745
|
+
# with a different label
|
|
746
|
+
for src, dst, data in g.edges(data=True):
|
|
747
|
+
src_cls = equivalence_classes.get(src, src)
|
|
748
|
+
dst_cls = equivalence_classes.get(dst, dst)
|
|
749
|
+
label = None if not data else data["label"]
|
|
750
|
+
if label is not None and out_graph.has_edge(src_cls, dst_cls):
|
|
751
|
+
# do not add the same edge twice
|
|
752
|
+
existing_labels = {
|
|
753
|
+
data_["label"]
|
|
754
|
+
for _, dst_cls_, data_ in out_graph.out_edges(src_cls, data=True)
|
|
755
|
+
if dst_cls_ == dst_cls and data
|
|
756
|
+
}
|
|
757
|
+
if label in existing_labels:
|
|
758
|
+
continue
|
|
759
|
+
out_graph.add_edge(src_cls, dst_cls, label=label)
|
|
760
|
+
|
|
761
|
+
return equivalence_classes, out_graph
|
|
762
|
+
|
|
763
|
+
def _generate_primitive_constraints(
|
|
764
|
+
self,
|
|
765
|
+
non_primitive_endpoints: set[TypeVariable | DerivedTypeVariable],
|
|
766
|
+
constraint_graph,
|
|
767
|
+
) -> set[TypeConstraint]:
|
|
768
|
+
constraints_0 = self._solve_constraints_between(constraint_graph, non_primitive_endpoints, PRIMITIVE_TYPES)
|
|
769
|
+
constraints_1 = self._solve_constraints_between(constraint_graph, PRIMITIVE_TYPES, non_primitive_endpoints)
|
|
770
|
+
return constraints_0 | constraints_1
|
|
771
|
+
|
|
772
|
+
@staticmethod
|
|
773
|
+
def _generate_transitive_subtype_constraints(
|
|
774
|
+
typevars: set[TypeVariable | DerivedTypeVariable],
|
|
775
|
+
constraints: set[TypeConstraint],
|
|
776
|
+
primitive_constraints: set[TypeConstraint],
|
|
777
|
+
) -> set[TypeConstraint]:
|
|
778
|
+
"""
|
|
779
|
+
Handling multiple type variables at once means we may miss some subtyping relationships between a type variable
|
|
780
|
+
and a primitive type (e.g., tv_1 <: tv_2 and tv_2 <: int, we may not see tv_1 <: int). This method attempts to
|
|
781
|
+
recover some of these missing constraints.
|
|
782
|
+
"""
|
|
783
|
+
|
|
784
|
+
tv_supertype = defaultdict(set)
|
|
785
|
+
for constraint in primitive_constraints:
|
|
786
|
+
if isinstance(constraint, Subtype) and SimpleSolver._typevar_inside_set(
|
|
787
|
+
constraint.super_type, PRIMITIVE_TYPES
|
|
788
|
+
):
|
|
789
|
+
tv_supertype[constraint.sub_type].add(constraint.super_type)
|
|
790
|
+
|
|
791
|
+
additional_constraints = set()
|
|
792
|
+
for constraint in constraints:
|
|
793
|
+
if (
|
|
794
|
+
isinstance(constraint, Subtype)
|
|
795
|
+
and isinstance(constraint.sub_type, TypeVariable)
|
|
796
|
+
and (
|
|
797
|
+
(isinstance(constraint.sub_type, DerivedTypeVariable) and constraint.sub_type.type_var in typevars)
|
|
798
|
+
or (not isinstance(constraint.sub_type, DerivedTypeVariable) and constraint.sub_type in typevars)
|
|
799
|
+
)
|
|
800
|
+
and constraint.super_type in tv_supertype
|
|
801
|
+
):
|
|
802
|
+
for supertype in tv_supertype[constraint.super_type]:
|
|
803
|
+
additional_constraints.add(Subtype(constraint.sub_type, supertype))
|
|
804
|
+
|
|
805
|
+
return additional_constraints
|
|
806
|
+
|
|
807
|
+
@staticmethod
|
|
808
|
+
def _typevars_from_constraints(constraints: set[TypeConstraint]) -> set[TypeVariable | DerivedTypeVariable]:
|
|
809
|
+
"""
|
|
810
|
+
Collect derived type variables from a set of constraints.
|
|
811
|
+
"""
|
|
812
|
+
|
|
813
|
+
typevars: set[TypeVariable | DerivedTypeVariable] = set()
|
|
814
|
+
for constraint in constraints:
|
|
815
|
+
if isinstance(constraint, Subtype):
|
|
816
|
+
if isinstance(constraint.sub_type, TypeVariable) and not (
|
|
817
|
+
isinstance(constraint.sub_type, DerivedTypeVariable)
|
|
818
|
+
and isinstance(constraint.sub_type.type_var, TypeConstant)
|
|
819
|
+
):
|
|
820
|
+
typevars.add(constraint.sub_type)
|
|
821
|
+
if isinstance(constraint.super_type, TypeVariable) and not (
|
|
822
|
+
isinstance(constraint.super_type, DerivedTypeVariable)
|
|
823
|
+
and isinstance(constraint.super_type.type_var, TypeConstant)
|
|
824
|
+
):
|
|
825
|
+
typevars.add(constraint.super_type)
|
|
826
|
+
# TODO: Other types of constraints?
|
|
827
|
+
return typevars
|
|
828
|
+
|
|
829
|
+
@staticmethod
|
|
830
|
+
def _typevar_from_primitive_constraint(constraint: TypeConstraint) -> TypeVariable | None:
|
|
831
|
+
if isinstance(constraint, Subtype):
|
|
832
|
+
if (
|
|
833
|
+
isinstance(constraint.sub_type, DerivedTypeVariable)
|
|
834
|
+
and type(constraint.sub_type.type_var) is TypeVariable
|
|
835
|
+
):
|
|
836
|
+
return constraint.sub_type.type_var
|
|
837
|
+
if type(constraint.sub_type) is TypeVariable:
|
|
838
|
+
return constraint.sub_type
|
|
839
|
+
if (
|
|
840
|
+
isinstance(constraint.super_type, DerivedTypeVariable)
|
|
841
|
+
and type(constraint.super_type.type_var) is TypeVariable
|
|
842
|
+
):
|
|
843
|
+
return constraint.super_type.type_var
|
|
844
|
+
if type(constraint.super_type) is TypeVariable:
|
|
845
|
+
return constraint.super_type
|
|
846
|
+
return None
|
|
847
|
+
|
|
848
|
+
@staticmethod
|
|
849
|
+
def _get_all_paths(
|
|
850
|
+
graph: networkx.DiGraph[TypeVariable | DerivedTypeVariable],
|
|
851
|
+
sketch: Sketch,
|
|
852
|
+
node: TypeVariable,
|
|
853
|
+
visited: dict[TypeVariable | DerivedTypeVariable, SketchNode],
|
|
854
|
+
):
|
|
855
|
+
if node not in graph:
|
|
856
|
+
return
|
|
857
|
+
curr_node = visited[node]
|
|
858
|
+
for _, succ, data in sorted(graph.out_edges(node, data=True), key=lambda x: str(x[1])):
|
|
859
|
+
label = data["label"]
|
|
860
|
+
if succ not in visited:
|
|
861
|
+
if isinstance(curr_node.typevar, DerivedTypeVariable):
|
|
862
|
+
base_typevar = curr_node.typevar.type_var
|
|
863
|
+
labels = curr_node.typevar.labels
|
|
864
|
+
elif isinstance(curr_node.typevar, TypeVariable):
|
|
865
|
+
base_typevar = curr_node.typevar
|
|
866
|
+
labels = ()
|
|
867
|
+
else:
|
|
868
|
+
raise TypeError("Unexpected")
|
|
869
|
+
labels += (label,)
|
|
870
|
+
succ_derived_typevar = new_dtv(
|
|
871
|
+
base_typevar,
|
|
872
|
+
labels=labels,
|
|
873
|
+
)
|
|
874
|
+
succ_node = SketchNode(succ_derived_typevar)
|
|
875
|
+
sketch.add_edge(curr_node, succ_node, label)
|
|
876
|
+
visited[succ] = succ_node
|
|
877
|
+
SimpleSolver._get_all_paths(graph, sketch, succ, visited)
|
|
878
|
+
del visited[succ]
|
|
879
|
+
else:
|
|
880
|
+
# a cycle exists
|
|
881
|
+
ref_node = RecursiveRefNode(visited[succ].typevar)
|
|
882
|
+
sketch.add_edge(curr_node, ref_node, label)
|
|
883
|
+
|
|
884
|
+
@staticmethod
|
|
885
|
+
def _unify(
|
|
886
|
+
equivalence_classes: dict,
|
|
887
|
+
cls0: TypeConstant | TypeVariable,
|
|
888
|
+
cls1: TypeConstant | TypeVariable,
|
|
889
|
+
graph: networkx.DiGraph,
|
|
890
|
+
) -> None:
|
|
891
|
+
# first convert cls0 and cls1 to their equivalence classes
|
|
892
|
+
cls0 = equivalence_classes.get(cls0, cls0)
|
|
893
|
+
cls1 = equivalence_classes.get(cls1, cls1)
|
|
894
|
+
|
|
895
|
+
# unify if needed
|
|
896
|
+
if cls0 != cls1:
|
|
897
|
+
# MakeEquiv
|
|
898
|
+
cls0_elems = {key for key, item in equivalence_classes.items() if item is cls0}
|
|
899
|
+
cls1_elems = {key for key, item in equivalence_classes.items() if item is cls1}
|
|
900
|
+
existing_elements = cls0_elems | cls1_elems
|
|
901
|
+
# pick a representative type variable and prioritize non-derived type variables
|
|
902
|
+
if not isinstance(cls0, DerivedTypeVariable):
|
|
903
|
+
rep_cls = cls0
|
|
904
|
+
elif not isinstance(cls1, DerivedTypeVariable):
|
|
905
|
+
rep_cls = cls1
|
|
906
|
+
else:
|
|
907
|
+
rep_cls = next(
|
|
908
|
+
iter(elem for elem in existing_elements if not isinstance(elem, DerivedTypeVariable)), cls0
|
|
909
|
+
)
|
|
910
|
+
for elem in existing_elements:
|
|
911
|
+
equivalence_classes[elem] = rep_cls
|
|
912
|
+
# the logic below refers to the retypd reference implementation. it is different from Algorithm E.1
|
|
913
|
+
# note that graph is used read-only in this method, so we do not need to make copy of edges
|
|
914
|
+
for _, dst0, data0 in graph.out_edges(cls0_elems, data=True):
|
|
915
|
+
if "label" in data0 and data0["label"] is not None:
|
|
916
|
+
for _, dst1, data1 in graph.out_edges(cls1_elems, data=True):
|
|
917
|
+
if data0["label"] == data1["label"] or (
|
|
918
|
+
isinstance(data0["label"], Load) and isinstance(data1["label"], Store)
|
|
919
|
+
):
|
|
920
|
+
SimpleSolver._unify(
|
|
921
|
+
equivalence_classes,
|
|
922
|
+
equivalence_classes.get(dst0, dst0),
|
|
923
|
+
equivalence_classes.get(dst1, dst1),
|
|
924
|
+
graph,
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
@staticmethod
|
|
928
|
+
def _eq_constraints_from_tvs(type_constraints: set[TypeConstraint]) -> set[TypeConstraint]:
|
|
929
|
+
"""
|
|
930
|
+
Generate more equivalence constraints based on known type variables.
|
|
931
|
+
|
|
932
|
+
Rules:
|
|
933
|
+
- tv == tv.+N
|
|
934
|
+
"""
|
|
935
|
+
# discover as many type variables as possible
|
|
936
|
+
typevars = set()
|
|
937
|
+
for constraint in type_constraints:
|
|
938
|
+
if isinstance(constraint, Subtype):
|
|
939
|
+
for t in (constraint.sub_type, constraint.super_type):
|
|
940
|
+
if isinstance(t, TypeVariable):
|
|
941
|
+
typevars.add(t)
|
|
942
|
+
elif isinstance(constraint, Equivalence):
|
|
943
|
+
for t in (constraint.type_a, constraint.type_b):
|
|
944
|
+
if isinstance(t, TypeVariable):
|
|
945
|
+
typevars.add(t)
|
|
946
|
+
elif isinstance(constraint, (Add, Sub)):
|
|
947
|
+
for t in (constraint.type_0, constraint.type_1, constraint.type_r):
|
|
948
|
+
if isinstance(t, TypeVariable):
|
|
949
|
+
typevars.add(t)
|
|
950
|
+
elif isinstance(constraint, Existence):
|
|
951
|
+
t = constraint.type_
|
|
952
|
+
if isinstance(t, TypeVariable):
|
|
953
|
+
typevars.add(t)
|
|
954
|
+
|
|
955
|
+
new_constraints = set()
|
|
956
|
+
tv_to_dtvs: defaultdict[TypeVariable, set[DerivedTypeVariable]] = defaultdict(set)
|
|
957
|
+
for tv in typevars:
|
|
958
|
+
if isinstance(tv, DerivedTypeVariable):
|
|
959
|
+
tv_to_dtvs[tv.type_var].add(tv)
|
|
960
|
+
|
|
961
|
+
for tv, dtvs in tv_to_dtvs.items():
|
|
962
|
+
for dtv in dtvs:
|
|
963
|
+
if isinstance(dtv.one_label(), (AddN, SubN)):
|
|
964
|
+
new_constraints.add(Equivalence(tv, dtv))
|
|
965
|
+
return new_constraints
|
|
966
|
+
|
|
967
|
+
@staticmethod
|
|
968
|
+
def _ptr_tvs_from_constraints(constraints: set[TypeConstraint]) -> set[TypeVariable]:
|
|
969
|
+
"""
|
|
970
|
+
Find TypeVariables that must be pointers (because they are dereferenced).
|
|
971
|
+
|
|
972
|
+
:param constraints: Type constraints.
|
|
973
|
+
:return: A set of TypeVariables that must be pointers.
|
|
974
|
+
"""
|
|
975
|
+
|
|
976
|
+
ptr_tvs = set()
|
|
977
|
+
for constraint in constraints:
|
|
978
|
+
if isinstance(constraint, Subtype):
|
|
979
|
+
for t in (constraint.sub_type, constraint.super_type):
|
|
980
|
+
if isinstance(t, DerivedTypeVariable) and isinstance(t.first_label(), (Store, Load)):
|
|
981
|
+
ptr_tvs.add(t.type_var)
|
|
982
|
+
|
|
983
|
+
return ptr_tvs
|
|
984
|
+
|
|
985
|
+
@staticmethod
|
|
986
|
+
def _remove_alignment_int_ptr_subtyping_constraints(
|
|
987
|
+
constraints: set[TypeConstraint], ptr_tvs: set[TypeVariable]
|
|
988
|
+
) -> set[TypeConstraint]:
|
|
989
|
+
"""
|
|
990
|
+
Eliminate incorrect subtyping constraints between int and pointer type variables. Such constraints are usually
|
|
991
|
+
the result of pointer alignment.
|
|
992
|
+
|
|
993
|
+
For example:
|
|
994
|
+
|
|
995
|
+
; msvcr120.dll, memmove, 0x18003C5FA
|
|
996
|
+
void* a1;
|
|
997
|
+
char* v21 = (char *)a1 + 32;
|
|
998
|
+
((char*)(&v21))[last_byte] = (uint8_t)v21 & 0xF0;
|
|
999
|
+
|
|
1000
|
+
Rules:
|
|
1001
|
+
- tv_int <: tv_ptr ==> remove
|
|
1002
|
+
"""
|
|
1003
|
+
|
|
1004
|
+
if not ptr_tvs:
|
|
1005
|
+
return constraints
|
|
1006
|
+
|
|
1007
|
+
new_constraints = set()
|
|
1008
|
+
for constraint in constraints:
|
|
1009
|
+
if isinstance(constraint, Subtype) and isinstance(constraint.sub_type, TypeConstant):
|
|
1010
|
+
if isinstance(constraint.super_type, DerivedTypeVariable):
|
|
1011
|
+
if constraint.super_type.type_var in ptr_tvs:
|
|
1012
|
+
# tv_int <: tv_ptr
|
|
1013
|
+
continue
|
|
1014
|
+
elif isinstance(constraint.super_type, TypeVariable) and constraint.super_type in ptr_tvs:
|
|
1015
|
+
# tv_int <: tv_ptr
|
|
1016
|
+
continue
|
|
1017
|
+
new_constraints.add(constraint)
|
|
1018
|
+
return new_constraints
|
|
1019
|
+
|
|
1020
|
+
def _eq_constraints_from_add(self, typevar: TypeVariable, ptr_tvs: set[TypeVariable]) -> set[TypeConstraint]:
|
|
1021
|
+
"""
|
|
1022
|
+
Handle Add constraints.
|
|
1023
|
+
|
|
1024
|
+
Rules:
|
|
1025
|
+
- tv_0 + tv_1 == tv_r ^ tv_0 is ptr ==> tv_r is ptr
|
|
1026
|
+
- tv_0 + tv_1 == tv_r ^ tv_1 is ptr ==> tv_r is ptr
|
|
1027
|
+
- tv_0 + tv_1.conv... == tv_r ^ tv_r is ptr ==> tv_0 is ptr
|
|
1028
|
+
"""
|
|
1029
|
+
if not ptr_tvs:
|
|
1030
|
+
return set()
|
|
1031
|
+
|
|
1032
|
+
new_constraints = set()
|
|
1033
|
+
for constraint in self._constraints[typevar]:
|
|
1034
|
+
if isinstance(constraint, Add):
|
|
1035
|
+
t0, t1, tr = constraint.type_0, constraint.type_1, constraint.type_r
|
|
1036
|
+
if not isinstance(t0, TypeConstant) and not isinstance(tr, TypeConstant) and t0 in ptr_tvs:
|
|
1037
|
+
new_constraints.add(Equivalence(t0, tr))
|
|
1038
|
+
elif not isinstance(t1, TypeConstant) and not isinstance(tr, TypeConstant) and t1 in ptr_tvs:
|
|
1039
|
+
new_constraints.add(Equivalence(t1, tr))
|
|
1040
|
+
elif not isinstance(tr, TypeConstant) and tr in ptr_tvs:
|
|
1041
|
+
if (
|
|
1042
|
+
not isinstance(t0, TypeConstant)
|
|
1043
|
+
and isinstance(t1, DerivedTypeVariable)
|
|
1044
|
+
and isinstance(t1.labels[-1], ConvertTo)
|
|
1045
|
+
):
|
|
1046
|
+
new_constraints.add(Equivalence(t0, tr))
|
|
1047
|
+
elif (
|
|
1048
|
+
not isinstance(t1, TypeConstant)
|
|
1049
|
+
and isinstance(t0, DerivedTypeVariable)
|
|
1050
|
+
and isinstance(t0.labels[-1], ConvertTo)
|
|
1051
|
+
):
|
|
1052
|
+
new_constraints.add(Equivalence(t1, tr))
|
|
1053
|
+
return new_constraints
|
|
1054
|
+
|
|
1055
|
+
def _eq_constraints_from_sub(self, typevar: TypeVariable, ptr_tvs: set[TypeVariable]) -> set[TypeConstraint]:
|
|
1056
|
+
"""
|
|
1057
|
+
Handle Sub constraints.
|
|
1058
|
+
|
|
1059
|
+
Rules:
|
|
1060
|
+
- tv_0 - tv_1 == tv_r ^ tv_0 is ptr ==> tv_r is ptr
|
|
1061
|
+
- tv_0 - tv_1 == tv_r ^ tv_r is ptr ==> tv_0 is ptr
|
|
1062
|
+
"""
|
|
1063
|
+
if not ptr_tvs:
|
|
1064
|
+
return set()
|
|
1065
|
+
|
|
1066
|
+
new_constraints = set()
|
|
1067
|
+
for constraint in self._constraints[typevar]:
|
|
1068
|
+
if (
|
|
1069
|
+
isinstance(constraint, Sub)
|
|
1070
|
+
and not isinstance(constraint.type_0, TypeConstant)
|
|
1071
|
+
and not isinstance(constraint.type_r, TypeConstant)
|
|
1072
|
+
and (constraint.type_0 in ptr_tvs or constraint.type_r in ptr_tvs)
|
|
1073
|
+
):
|
|
1074
|
+
eq = Equivalence(constraint.type_0, constraint.type_r)
|
|
1075
|
+
new_constraints.add(eq)
|
|
1076
|
+
return new_constraints
|
|
1077
|
+
|
|
1078
|
+
@staticmethod
|
|
1079
|
+
def _discover_equivalence(constraints: set[TypeConstraint]) -> set[Equivalence]:
|
|
1080
|
+
"""
|
|
1081
|
+
a <:b && b <: a ==> a == b
|
|
1082
|
+
"""
|
|
1083
|
+
|
|
1084
|
+
new_eq_constraints: set[Equivalence] = set()
|
|
1085
|
+
subtypes = defaultdict(set)
|
|
1086
|
+
for constraint in constraints:
|
|
1087
|
+
if isinstance(constraint, Subtype):
|
|
1088
|
+
sub_type = constraint.sub_type
|
|
1089
|
+
super_type = constraint.super_type
|
|
1090
|
+
subtypes[sub_type].add(super_type)
|
|
1091
|
+
|
|
1092
|
+
# check everything
|
|
1093
|
+
seen = set()
|
|
1094
|
+
for tv, tv_supers in subtypes.items():
|
|
1095
|
+
for tv_super in tv_supers:
|
|
1096
|
+
if tv_super in subtypes and tv in subtypes[tv_super]: # noqa: SIM102
|
|
1097
|
+
# we have a pair of subtypes that are equivalent
|
|
1098
|
+
if (tv, tv_super) not in seen and (tv_super, tv) not in seen:
|
|
1099
|
+
new_eq_constraints.add(Equivalence(tv, tv_super))
|
|
1100
|
+
seen.add((tv, tv_super))
|
|
1101
|
+
|
|
1102
|
+
_l.debug(
|
|
1103
|
+
"Discovered %d equivalence constraints from %d constraints.", len(new_eq_constraints), len(constraints)
|
|
1104
|
+
)
|
|
1105
|
+
return new_eq_constraints
|
|
1106
|
+
|
|
1107
|
+
@staticmethod
|
|
1108
|
+
def _handle_equivalence(
|
|
1109
|
+
constraint_set: set[TypeConstraint],
|
|
1110
|
+
) -> tuple[set[TypeConstraint], dict[TypeVariable, TypeVariable | TypeConstant]]:
|
|
1111
|
+
graph = networkx.Graph()
|
|
1112
|
+
|
|
1113
|
+
replacements: dict[TypeVariable, TypeVariable | TypeConstant] = {}
|
|
1114
|
+
|
|
1115
|
+
# collect equivalence relations
|
|
1116
|
+
for constraint in constraint_set:
|
|
1117
|
+
if isinstance(constraint, Equivalence):
|
|
1118
|
+
# | type_a == type_b
|
|
1119
|
+
# we apply unification and removes one of them
|
|
1120
|
+
ta, tb = constraint.type_a, constraint.type_b
|
|
1121
|
+
if isinstance(ta, TypeConstant) and isinstance(tb, TypeVariable):
|
|
1122
|
+
# replace tb with ta
|
|
1123
|
+
replacements[tb] = ta
|
|
1124
|
+
elif isinstance(ta, TypeVariable) and isinstance(tb, TypeConstant):
|
|
1125
|
+
# replace ta with tb
|
|
1126
|
+
replacements[ta] = tb
|
|
1127
|
+
else:
|
|
1128
|
+
# they are both type variables. we will determine a representative later
|
|
1129
|
+
graph.add_edge(ta, tb)
|
|
1130
|
+
|
|
1131
|
+
for components in networkx.connected_components(graph):
|
|
1132
|
+
components_lst = sorted(components, key=str)
|
|
1133
|
+
|
|
1134
|
+
tc = None
|
|
1135
|
+
for tv in components_lst:
|
|
1136
|
+
if tv in replacements and isinstance(replacements[tv], TypeConstant):
|
|
1137
|
+
tc = replacements[tv]
|
|
1138
|
+
break
|
|
1139
|
+
representative = tc if tc is not None else components_lst[0]
|
|
1140
|
+
for tv in components_lst[1:]:
|
|
1141
|
+
replacements[tv] = representative
|
|
1142
|
+
|
|
1143
|
+
constraints = SimpleSolver._rewrite_constraints_with_replacements(constraint_set, replacements)
|
|
1144
|
+
|
|
1145
|
+
# import pprint
|
|
1146
|
+
# print("Replacements")
|
|
1147
|
+
# pprint.pprint(replacements)
|
|
1148
|
+
# print("Constraints (after replacement)")
|
|
1149
|
+
# pprint.pprint(constraints)
|
|
1150
|
+
|
|
1151
|
+
return constraints, replacements
|
|
1152
|
+
|
|
1153
|
+
@staticmethod
|
|
1154
|
+
def _rewrite_typeconstant_with_replacements(
|
|
1155
|
+
tc: TypeConstant, replacements: dict[TypeConstant, TypeConstant]
|
|
1156
|
+
) -> TypeConstant:
|
|
1157
|
+
if isinstance(tc, (Pointer, Struct)):
|
|
1158
|
+
if tc in replacements:
|
|
1159
|
+
return replacements[tc]
|
|
1160
|
+
return tc.replace(replacements)
|
|
1161
|
+
return tc
|
|
1162
|
+
|
|
1163
|
+
@staticmethod
|
|
1164
|
+
def _rewrite_constraints_with_replacements(
|
|
1165
|
+
constraints: set[TypeConstraint], replacements: dict[TypeVariable, TypeVariable | TypeConstant]
|
|
1166
|
+
) -> set[TypeConstraint]:
|
|
1167
|
+
# replace constraints according to a dictionary of type variable replacements
|
|
1168
|
+
if not replacements:
|
|
1169
|
+
return constraints
|
|
1170
|
+
|
|
1171
|
+
replaced_constraints = set()
|
|
1172
|
+
for constraint in constraints:
|
|
1173
|
+
if isinstance(constraint, Existence):
|
|
1174
|
+
replaced, new_constraint = constraint.replace(replacements)
|
|
1175
|
+
|
|
1176
|
+
if replaced:
|
|
1177
|
+
replaced_constraints.add(new_constraint)
|
|
1178
|
+
else:
|
|
1179
|
+
replaced_constraints.add(constraint)
|
|
1180
|
+
|
|
1181
|
+
elif isinstance(constraint, Subtype):
|
|
1182
|
+
# subtype <: supertype
|
|
1183
|
+
# replace type variables
|
|
1184
|
+
replaced, new_constraint = constraint.replace(replacements)
|
|
1185
|
+
|
|
1186
|
+
if replaced:
|
|
1187
|
+
replaced_constraints.add(new_constraint)
|
|
1188
|
+
else:
|
|
1189
|
+
replaced_constraints.add(constraint)
|
|
1190
|
+
return replaced_constraints
|
|
1191
|
+
|
|
1192
|
+
@staticmethod
|
|
1193
|
+
def _filter_constraints(constraints: set[TypeConstraint]) -> set[TypeConstraint]:
|
|
1194
|
+
"""
|
|
1195
|
+
Filter out constraints that we don't yet support.
|
|
1196
|
+
"""
|
|
1197
|
+
|
|
1198
|
+
filtered_constraints = set()
|
|
1199
|
+
for constraint in constraints:
|
|
1200
|
+
dropped = False
|
|
1201
|
+
if isinstance(constraint, Subtype) and (
|
|
1202
|
+
(isinstance(constraint.sub_type, TypeConstant) and isinstance(constraint.super_type, TypeConstant))
|
|
1203
|
+
or (
|
|
1204
|
+
isinstance(constraint.sub_type, DerivedTypeVariable)
|
|
1205
|
+
and isinstance(constraint.sub_type.labels[-1], ConvertTo)
|
|
1206
|
+
)
|
|
1207
|
+
or (
|
|
1208
|
+
isinstance(constraint.sub_type, TypeVariable)
|
|
1209
|
+
and isinstance(constraint.super_type, TypeVariable)
|
|
1210
|
+
and constraint.sub_type == constraint.super_type
|
|
1211
|
+
)
|
|
1212
|
+
):
|
|
1213
|
+
dropped = True
|
|
1214
|
+
|
|
1215
|
+
if not dropped:
|
|
1216
|
+
filtered_constraints.add(constraint)
|
|
1217
|
+
|
|
1218
|
+
return filtered_constraints
|
|
1219
|
+
|
|
1220
|
+
@staticmethod
|
|
1221
|
+
def _filter_leaf_typevars(
|
|
1222
|
+
constraints: set[TypeConstraint], tvs_to_solve: set[TypeVariable]
|
|
1223
|
+
) -> tuple[set[TypeConstraint], dict[TypeVariable, TypeVariable]]:
|
|
1224
|
+
"""
|
|
1225
|
+
Filter out leaf type variables that only appear once in the constraints. These type variables are not
|
|
1226
|
+
interesting and can be removed from the constraints.
|
|
1227
|
+
"""
|
|
1228
|
+
|
|
1229
|
+
sub_typevars = defaultdict(set)
|
|
1230
|
+
tv_to_dtvs: dict[TypeVariable, set[TypeVariable | DerivedTypeVariable]] = defaultdict(set)
|
|
1231
|
+
for constraint in constraints:
|
|
1232
|
+
if isinstance(constraint, Subtype):
|
|
1233
|
+
if isinstance(constraint.sub_type, TypeVariable):
|
|
1234
|
+
sub_typevars[constraint.sub_type].add(constraint.super_type)
|
|
1235
|
+
for tv in [constraint.sub_type, constraint.super_type]:
|
|
1236
|
+
if isinstance(tv, DerivedTypeVariable) and not isinstance(constraint.sub_type, TypeConstant):
|
|
1237
|
+
tv_to_dtvs[tv.type_var].add(constraint.sub_type)
|
|
1238
|
+
elif isinstance(tv, TypeVariable) and not isinstance(constraint.sub_type, TypeConstant):
|
|
1239
|
+
tv_to_dtvs[tv].add(constraint.sub_type)
|
|
1240
|
+
|
|
1241
|
+
ub_subtypes: dict[TypeVariable, TypeVariable] = {}
|
|
1242
|
+
for tv, dtvs in tv_to_dtvs.items():
|
|
1243
|
+
if len(dtvs) == 1 and tv in sub_typevars and len(sub_typevars[tv]) == 1:
|
|
1244
|
+
ub = next(iter(sub_typevars[tv]))
|
|
1245
|
+
if ub in tvs_to_solve:
|
|
1246
|
+
ub_subtypes[tv] = ub
|
|
1247
|
+
|
|
1248
|
+
filtered_constraints = set()
|
|
1249
|
+
for constraint in constraints:
|
|
1250
|
+
if isinstance(constraint, Subtype):
|
|
1251
|
+
if constraint.sub_type in ub_subtypes:
|
|
1252
|
+
continue
|
|
1253
|
+
if constraint.sub_type == constraint.super_type:
|
|
1254
|
+
continue
|
|
1255
|
+
filtered_constraints.add(constraint)
|
|
1256
|
+
|
|
1257
|
+
return filtered_constraints, ub_subtypes
|
|
1258
|
+
|
|
1259
|
+
def _degrade_constraint_set(self, constraints: set[TypeConstraint]) -> set[TypeConstraint]:
|
|
1260
|
+
"""
|
|
1261
|
+
Degrade the constraint set to a smaller set of constraints to speed up the DFA generation process.
|
|
1262
|
+
"""
|
|
1263
|
+
|
|
1264
|
+
tv_with_ls = defaultdict(set) # tv_with_ls are type variables with Loads or Stores
|
|
1265
|
+
graph = networkx.Graph()
|
|
1266
|
+
|
|
1267
|
+
for constraint in constraints:
|
|
1268
|
+
if isinstance(constraint, Subtype):
|
|
1269
|
+
if isinstance(constraint.sub_type, DerivedTypeVariable) and isinstance(
|
|
1270
|
+
constraint.sub_type.labels[0], (Load, Store)
|
|
1271
|
+
):
|
|
1272
|
+
tv_with_ls[constraint.sub_type.type_var].add(constraint.sub_type)
|
|
1273
|
+
if type(constraint.sub_type) is TypeVariable and type(constraint.super_type) is TypeVariable:
|
|
1274
|
+
graph.add_edge(constraint.sub_type, constraint.super_type)
|
|
1275
|
+
|
|
1276
|
+
tv_to_degrade = set()
|
|
1277
|
+
for tv, dtvs in tv_with_ls.items():
|
|
1278
|
+
if len(dtvs) > 5:
|
|
1279
|
+
# degrade all subtype relationships involving this type variable to equivalence
|
|
1280
|
+
tv_to_degrade.add(tv)
|
|
1281
|
+
|
|
1282
|
+
replacements = {}
|
|
1283
|
+
for components in networkx.connected_components(graph):
|
|
1284
|
+
if len(components) == 1:
|
|
1285
|
+
continue
|
|
1286
|
+
if any(tv in tv_to_degrade for tv in components):
|
|
1287
|
+
components_lst = sorted(components, key=str)
|
|
1288
|
+
representative = components_lst[0]
|
|
1289
|
+
for tv in components_lst[1:]:
|
|
1290
|
+
replacements[tv] = representative
|
|
1291
|
+
|
|
1292
|
+
degraded_constraints = self._rewrite_constraints_with_replacements(constraints, replacements)
|
|
1293
|
+
|
|
1294
|
+
# discover more equivalence relations
|
|
1295
|
+
eq_constraints = self._discover_equivalence(degraded_constraints)
|
|
1296
|
+
_l.debug("Discovered %d equivalence constraints from degraded constraints.", len(eq_constraints))
|
|
1297
|
+
if eq_constraints:
|
|
1298
|
+
degraded_constraints, eq_replacements = self._handle_equivalence(degraded_constraints | eq_constraints)
|
|
1299
|
+
self._equivalence |= eq_replacements
|
|
1300
|
+
|
|
1301
|
+
# filter them
|
|
1302
|
+
degraded_constraints = self._filter_constraints(degraded_constraints)
|
|
1303
|
+
|
|
1304
|
+
self._equivalence |= replacements
|
|
1305
|
+
return degraded_constraints
|
|
1306
|
+
|
|
1307
|
+
@staticmethod
|
|
1308
|
+
def _drop_missized_constraints(tvs: set[TypeVariable], constraints: set[TypeConstraint]) -> set[TypeConstraint]:
|
|
1309
|
+
"""
|
|
1310
|
+
This is very much a hack - sometimes we get constraints about a type variable with conflicting sizes. We drop
|
|
1311
|
+
the ones with determined, smaller sizes.
|
|
1312
|
+
"""
|
|
1313
|
+
|
|
1314
|
+
to_drop = set()
|
|
1315
|
+
for tv in tvs:
|
|
1316
|
+
tv_sizes = defaultdict(set) # bytes -> set[TypeConstraint]
|
|
1317
|
+
for constraint in constraints:
|
|
1318
|
+
if isinstance(constraint, Subtype):
|
|
1319
|
+
if constraint.sub_type == tv and isinstance(constraint.super_type, DerivedTypeVariable):
|
|
1320
|
+
last_field = constraint.super_type.labels[-1]
|
|
1321
|
+
if isinstance(last_field, HasField):
|
|
1322
|
+
sz = last_field.bits if last_field.bits == MAX_POINTSTO_BITS else last_field.bits // 8
|
|
1323
|
+
tv_sizes[sz].add(constraint)
|
|
1324
|
+
elif isinstance(constraint.sub_type, (Int, Float)) and constraint.super_type == tv:
|
|
1325
|
+
tv_sizes[constraint.sub_type.SIZE].add(constraint)
|
|
1326
|
+
|
|
1327
|
+
if not tv_sizes:
|
|
1328
|
+
continue
|
|
1329
|
+
|
|
1330
|
+
max_size = MAX_POINTSTO_BITS if MAX_POINTSTO_BITS in tv_sizes else max(tv_sizes)
|
|
1331
|
+
for size, cs in tv_sizes.items():
|
|
1332
|
+
if size != max_size:
|
|
1333
|
+
to_drop |= cs
|
|
1334
|
+
|
|
1335
|
+
return constraints.difference(to_drop)
|
|
1336
|
+
|
|
1337
|
+
def _convert_arrays(self, constraints):
|
|
1338
|
+
for constraint in constraints:
|
|
1339
|
+
if not isinstance(constraint, Existence):
|
|
1340
|
+
continue
|
|
1341
|
+
inner = constraint.type_
|
|
1342
|
+
if (
|
|
1343
|
+
isinstance(inner, DerivedTypeVariable)
|
|
1344
|
+
and isinstance(inner.one_label(), IsArray)
|
|
1345
|
+
and inner.type_var in self.solution
|
|
1346
|
+
):
|
|
1347
|
+
curr_type = self.solution[inner.type_var]
|
|
1348
|
+
if (
|
|
1349
|
+
isinstance(curr_type, Pointer)
|
|
1350
|
+
and isinstance(curr_type.basetype, Struct)
|
|
1351
|
+
and 0 in curr_type.basetype.fields
|
|
1352
|
+
):
|
|
1353
|
+
# replace all fields with the first field
|
|
1354
|
+
first_field = curr_type.basetype.fields[0]
|
|
1355
|
+
for offset in curr_type.basetype.fields:
|
|
1356
|
+
curr_type.basetype.fields[offset] = first_field
|
|
1357
|
+
|
|
1358
|
+
#
|
|
1359
|
+
# Constraint graph
|
|
1360
|
+
#
|
|
1361
|
+
|
|
1362
|
+
@staticmethod
|
|
1363
|
+
def _generate_constraint_subset(
|
|
1364
|
+
constraints: set[TypeConstraint], typevars: set[TypeVariable]
|
|
1365
|
+
) -> tuple[set[TypeConstraint], set[TypeVariable]]:
|
|
1366
|
+
subset = set()
|
|
1367
|
+
related_typevars = set(typevars)
|
|
1368
|
+
while True:
|
|
1369
|
+
new = set()
|
|
1370
|
+
for constraint in constraints:
|
|
1371
|
+
if constraint in subset:
|
|
1372
|
+
continue
|
|
1373
|
+
if isinstance(constraint, Subtype):
|
|
1374
|
+
if isinstance(constraint.sub_type, DerivedTypeVariable):
|
|
1375
|
+
subt = constraint.sub_type.type_var
|
|
1376
|
+
elif isinstance(constraint.sub_type, TypeVariable):
|
|
1377
|
+
subt = constraint.sub_type
|
|
1378
|
+
else:
|
|
1379
|
+
subt = None
|
|
1380
|
+
if isinstance(constraint.super_type, DerivedTypeVariable):
|
|
1381
|
+
supert = constraint.super_type.type_var
|
|
1382
|
+
elif isinstance(constraint.super_type, TypeVariable):
|
|
1383
|
+
supert = constraint.super_type
|
|
1384
|
+
else:
|
|
1385
|
+
supert = None
|
|
1386
|
+
if subt in related_typevars or supert in related_typevars:
|
|
1387
|
+
new.add(constraint)
|
|
1388
|
+
if subt is not None:
|
|
1389
|
+
related_typevars.add(subt)
|
|
1390
|
+
if supert is not None:
|
|
1391
|
+
related_typevars.add(supert)
|
|
1392
|
+
if not new:
|
|
1393
|
+
break
|
|
1394
|
+
subset |= new
|
|
1395
|
+
return subset, related_typevars
|
|
1396
|
+
|
|
1397
|
+
def _generate_constraint_graph(
|
|
1398
|
+
self, constraints: set[TypeConstraint], interesting_variables: set[DerivedTypeVariable]
|
|
1399
|
+
) -> networkx.DiGraph:
|
|
1400
|
+
"""
|
|
1401
|
+
A constraint graph is the same as the finite state transducer that is presented in Appendix D in the retypd
|
|
1402
|
+
paper.
|
|
1403
|
+
"""
|
|
1404
|
+
|
|
1405
|
+
graph = networkx.DiGraph()
|
|
1406
|
+
for constraint in constraints:
|
|
1407
|
+
if isinstance(constraint, Subtype):
|
|
1408
|
+
self._constraint_graph_add_edges(
|
|
1409
|
+
graph, constraint.sub_type, constraint.super_type, interesting_variables
|
|
1410
|
+
)
|
|
1411
|
+
self._constraint_graph_saturate(graph)
|
|
1412
|
+
self._constraint_graph_remove_self_loops(graph)
|
|
1413
|
+
self._constraint_graph_recall_forget_split(graph)
|
|
1414
|
+
return graph
|
|
1415
|
+
|
|
1416
|
+
@staticmethod
|
|
1417
|
+
def _constraint_graph_add_recall_edges(graph: networkx.DiGraph, node: ConstraintGraphNode) -> None:
|
|
1418
|
+
while True:
|
|
1419
|
+
r = node.forget_last_label()
|
|
1420
|
+
if r is None:
|
|
1421
|
+
break
|
|
1422
|
+
prefix, last_label = r
|
|
1423
|
+
graph.add_edge(prefix, node, label=(last_label, "recall"))
|
|
1424
|
+
node = prefix
|
|
1425
|
+
|
|
1426
|
+
@staticmethod
|
|
1427
|
+
def _constraint_graph_add_forget_edges(graph: networkx.DiGraph, node: ConstraintGraphNode) -> None:
|
|
1428
|
+
while True:
|
|
1429
|
+
r = node.forget_last_label()
|
|
1430
|
+
if r is None:
|
|
1431
|
+
break
|
|
1432
|
+
prefix, last_label = r
|
|
1433
|
+
graph.add_edge(node, prefix, label=(last_label, "forget"))
|
|
1434
|
+
node = prefix
|
|
1435
|
+
|
|
1436
|
+
def _constraint_graph_add_edges(
|
|
1437
|
+
self,
|
|
1438
|
+
graph: networkx.DiGraph,
|
|
1439
|
+
subtype: TypeVariable | DerivedTypeVariable | TypeConstant,
|
|
1440
|
+
supertype: TypeVariable | DerivedTypeVariable | TypeConstant,
|
|
1441
|
+
interesting_variables: set[TypeVariable | DerivedTypeVariable | TypeConstant],
|
|
1442
|
+
):
|
|
1443
|
+
# left and right tags
|
|
1444
|
+
if self._typevar_inside_set(self._to_typevar_or_typeconst(subtype), interesting_variables):
|
|
1445
|
+
left_tag = ConstraintGraphTag.LEFT
|
|
1446
|
+
else:
|
|
1447
|
+
left_tag = ConstraintGraphTag.UNKNOWN
|
|
1448
|
+
if self._typevar_inside_set(self._to_typevar_or_typeconst(supertype), interesting_variables):
|
|
1449
|
+
right_tag = ConstraintGraphTag.RIGHT
|
|
1450
|
+
else:
|
|
1451
|
+
right_tag = ConstraintGraphTag.UNKNOWN
|
|
1452
|
+
# nodes
|
|
1453
|
+
forward_src = ConstraintGraphNode(subtype, Variance.COVARIANT, left_tag, FORGOTTEN.PRE_FORGOTTEN)
|
|
1454
|
+
forward_dst = ConstraintGraphNode(supertype, Variance.COVARIANT, right_tag, FORGOTTEN.PRE_FORGOTTEN)
|
|
1455
|
+
graph.add_edge(forward_src, forward_dst)
|
|
1456
|
+
# add recall edges and forget edges
|
|
1457
|
+
self._constraint_graph_add_recall_edges(graph, forward_src)
|
|
1458
|
+
self._constraint_graph_add_forget_edges(graph, forward_dst)
|
|
1459
|
+
|
|
1460
|
+
# backward edges
|
|
1461
|
+
backward_src = forward_dst.inverse()
|
|
1462
|
+
backward_dst = forward_src.inverse()
|
|
1463
|
+
graph.add_edge(backward_src, backward_dst)
|
|
1464
|
+
self._constraint_graph_add_recall_edges(graph, backward_src)
|
|
1465
|
+
self._constraint_graph_add_forget_edges(graph, backward_dst)
|
|
1466
|
+
|
|
1467
|
+
@staticmethod
|
|
1468
|
+
def _constraint_graph_saturate(graph: networkx.DiGraph) -> None:
|
|
1469
|
+
"""
|
|
1470
|
+
The saturation algorithm D.2 as described in Appendix of the retypd paper.
|
|
1471
|
+
"""
|
|
1472
|
+
R: defaultdict[ConstraintGraphNode, set[tuple[BaseLabel, ConstraintGraphNode]]] = defaultdict(set)
|
|
1473
|
+
|
|
1474
|
+
# initialize the reaching-push sets R(x)
|
|
1475
|
+
for x, y, data in graph.edges(data=True):
|
|
1476
|
+
if "label" in data and data.get("label")[1] == "forget": # type:ignore
|
|
1477
|
+
d = data["label"][0], x
|
|
1478
|
+
R[y].add(d)
|
|
1479
|
+
|
|
1480
|
+
# repeat ... until fixed point
|
|
1481
|
+
changed = True
|
|
1482
|
+
while changed:
|
|
1483
|
+
changed = False
|
|
1484
|
+
for x, y, data in graph.edges(data=True):
|
|
1485
|
+
if "label" not in data:
|
|
1486
|
+
if R[y].issuperset(R[x]):
|
|
1487
|
+
continue
|
|
1488
|
+
changed = True
|
|
1489
|
+
R[y] |= R[x]
|
|
1490
|
+
for x, y, data in graph.edges(data=True):
|
|
1491
|
+
lbl = data.get("label")
|
|
1492
|
+
if lbl and lbl[1] == "recall":
|
|
1493
|
+
for _label, z in R[x]:
|
|
1494
|
+
if lbl[0] == _label and not graph.has_edge(z, y):
|
|
1495
|
+
changed = True
|
|
1496
|
+
graph.add_edge(z, y)
|
|
1497
|
+
v_contravariant = []
|
|
1498
|
+
for node in graph.nodes:
|
|
1499
|
+
node: ConstraintGraphNode
|
|
1500
|
+
if node.variance == Variance.CONTRAVARIANT:
|
|
1501
|
+
v_contravariant.append(node)
|
|
1502
|
+
# lazily apply saturation rules corresponding to S-Pointer
|
|
1503
|
+
for x in v_contravariant:
|
|
1504
|
+
for z_label, z in R[x]:
|
|
1505
|
+
label = None
|
|
1506
|
+
if isinstance(z_label, Store):
|
|
1507
|
+
label = Load()
|
|
1508
|
+
elif isinstance(z_label, Load):
|
|
1509
|
+
label = Store()
|
|
1510
|
+
if label is not None:
|
|
1511
|
+
x_inverse = x.inverse_wo_tag()
|
|
1512
|
+
d = label, z
|
|
1513
|
+
if d not in R[x_inverse]:
|
|
1514
|
+
changed = True
|
|
1515
|
+
R[x_inverse].add(d)
|
|
1516
|
+
|
|
1517
|
+
@staticmethod
|
|
1518
|
+
def _constraint_graph_remove_self_loops(graph: networkx.DiGraph):
|
|
1519
|
+
for node in list(graph.nodes):
|
|
1520
|
+
if graph.has_edge(node, node):
|
|
1521
|
+
graph.remove_edge(node, node)
|
|
1522
|
+
|
|
1523
|
+
@staticmethod
|
|
1524
|
+
def _constraint_graph_recall_forget_split(graph: networkx.DiGraph):
|
|
1525
|
+
"""
|
|
1526
|
+
Ensure that recall edges are not reachable after traversing a forget node.
|
|
1527
|
+
"""
|
|
1528
|
+
for src, dst, data in list(graph.edges(data=True)):
|
|
1529
|
+
src: ConstraintGraphNode
|
|
1530
|
+
dst: ConstraintGraphNode
|
|
1531
|
+
if "label" in data and data["label"][1] == "recall":
|
|
1532
|
+
continue
|
|
1533
|
+
forget_src = ConstraintGraphNode(src.typevar, src.variance, src.tag, FORGOTTEN.POST_FORGOTTEN)
|
|
1534
|
+
forget_dst = ConstraintGraphNode(dst.typevar, dst.variance, dst.tag, FORGOTTEN.POST_FORGOTTEN)
|
|
1535
|
+
if "label" in data and data["label"][1] == "forget":
|
|
1536
|
+
graph.remove_edge(src, dst)
|
|
1537
|
+
graph.add_edge(src, forget_dst, **data)
|
|
1538
|
+
graph.add_edge(forget_src, forget_dst, **data)
|
|
1539
|
+
|
|
1540
|
+
@staticmethod
|
|
1541
|
+
def _to_typevar_or_typeconst(obj: TypeVariable | DerivedTypeVariable | TypeConstant) -> TypeVariable | TypeConstant:
|
|
1542
|
+
if isinstance(obj, DerivedTypeVariable):
|
|
1543
|
+
return SimpleSolver._to_typevar_or_typeconst(obj.type_var)
|
|
1544
|
+
if isinstance(obj, (TypeVariable, TypeConstant)):
|
|
1545
|
+
return obj
|
|
1546
|
+
raise TypeError(f"Unsupported type {type(obj)}")
|
|
1547
|
+
|
|
1548
|
+
#
|
|
1549
|
+
# Graph solver
|
|
1550
|
+
#
|
|
1551
|
+
|
|
1552
|
+
@staticmethod
|
|
1553
|
+
def _typevar_inside_set(typevar, typevar_set: set[TypeConstant | TypeVariable | DerivedTypeVariable]) -> bool:
|
|
1554
|
+
if typevar in typevar_set:
|
|
1555
|
+
return True
|
|
1556
|
+
if isinstance(typevar, Struct) and Struct_ in typevar_set:
|
|
1557
|
+
return True
|
|
1558
|
+
if isinstance(typevar, Array) and Array_ in typevar_set:
|
|
1559
|
+
return SimpleSolver._typevar_inside_set(typevar.element, typevar_set)
|
|
1560
|
+
if isinstance(typevar, Pointer) and (Pointer32_ in typevar_set or Pointer64_ in typevar_set):
|
|
1561
|
+
return SimpleSolver._typevar_inside_set(typevar.basetype, typevar_set)
|
|
1562
|
+
return False
|
|
1563
|
+
|
|
1564
|
+
def _solve_constraints_between(
|
|
1565
|
+
self,
|
|
1566
|
+
graph: networkx.DiGraph,
|
|
1567
|
+
starts: set[TypeConstant | TypeVariable | DerivedTypeVariable],
|
|
1568
|
+
ends: set[TypeConstant | TypeVariable | DerivedTypeVariable],
|
|
1569
|
+
) -> set[TypeConstraint]:
|
|
1570
|
+
start_nodes = set()
|
|
1571
|
+
end_nodes = set()
|
|
1572
|
+
for node in graph.nodes:
|
|
1573
|
+
node: ConstraintGraphNode
|
|
1574
|
+
if (
|
|
1575
|
+
self._typevar_inside_set(self._to_typevar_or_typeconst(node.typevar), starts)
|
|
1576
|
+
and node.tag == ConstraintGraphTag.LEFT
|
|
1577
|
+
):
|
|
1578
|
+
start_nodes.add(node)
|
|
1579
|
+
if (
|
|
1580
|
+
self._typevar_inside_set(self._to_typevar_or_typeconst(node.typevar), ends)
|
|
1581
|
+
and node.tag == ConstraintGraphTag.RIGHT
|
|
1582
|
+
):
|
|
1583
|
+
end_nodes.add(node)
|
|
1584
|
+
|
|
1585
|
+
if not start_nodes or not end_nodes:
|
|
1586
|
+
return set()
|
|
1587
|
+
|
|
1588
|
+
dfa_solver = DFAConstraintSolver()
|
|
1589
|
+
try:
|
|
1590
|
+
return dfa_solver.generate_constraints_between(graph, start_nodes, end_nodes)
|
|
1591
|
+
except EmptyEpsilonNFAError:
|
|
1592
|
+
return set()
|
|
1593
|
+
|
|
1594
|
+
#
|
|
1595
|
+
# Type lattice
|
|
1596
|
+
#
|
|
1597
|
+
|
|
1598
|
+
def join(self, t1: TypeConstant | TypeVariable, t2: TypeConstant | TypeVariable) -> TypeConstant:
|
|
1599
|
+
abstract_t1 = self.abstract(t1)
|
|
1600
|
+
abstract_t2 = self.abstract(t2)
|
|
1601
|
+
if abstract_t1 in self._base_lattice and abstract_t2 in self._base_lattice:
|
|
1602
|
+
ancestor = networkx.lowest_common_ancestor(self._base_lattice, abstract_t1, abstract_t2)
|
|
1603
|
+
|
|
1604
|
+
if (
|
|
1605
|
+
isinstance(ancestor, Pointer)
|
|
1606
|
+
and isinstance(abstract_t1, Pointer)
|
|
1607
|
+
and isinstance(abstract_t2, Pointer)
|
|
1608
|
+
and isinstance(t1, Pointer)
|
|
1609
|
+
and isinstance(t2, Pointer)
|
|
1610
|
+
):
|
|
1611
|
+
return ancestor.__class__(self.join(t1.basetype, t2.basetype))
|
|
1612
|
+
|
|
1613
|
+
if ancestor == abstract_t1:
|
|
1614
|
+
return t1
|
|
1615
|
+
if ancestor == abstract_t2:
|
|
1616
|
+
return t2
|
|
1617
|
+
return ancestor
|
|
1618
|
+
if t1 == Bottom_:
|
|
1619
|
+
return t2
|
|
1620
|
+
if t2 == Bottom_:
|
|
1621
|
+
return t1
|
|
1622
|
+
return Bottom_
|
|
1623
|
+
|
|
1624
|
+
def meet(self, t1: TypeConstant | TypeVariable, t2: TypeConstant | TypeVariable) -> TypeConstant:
|
|
1625
|
+
abstract_t1 = self.abstract(t1)
|
|
1626
|
+
abstract_t2 = self.abstract(t2)
|
|
1627
|
+
if abstract_t1 in self._base_lattice_inverted and abstract_t2 in self._base_lattice_inverted:
|
|
1628
|
+
ancestor = networkx.lowest_common_ancestor(self._base_lattice_inverted, abstract_t1, abstract_t2)
|
|
1629
|
+
|
|
1630
|
+
if (
|
|
1631
|
+
isinstance(ancestor, Pointer)
|
|
1632
|
+
and isinstance(abstract_t1, Pointer)
|
|
1633
|
+
and isinstance(abstract_t2, Pointer)
|
|
1634
|
+
and isinstance(t1, Pointer)
|
|
1635
|
+
and isinstance(t2, Pointer)
|
|
1636
|
+
):
|
|
1637
|
+
return ancestor.__class__(self.meet(t1.basetype, t2.basetype))
|
|
1638
|
+
|
|
1639
|
+
if ancestor == abstract_t1:
|
|
1640
|
+
return t1
|
|
1641
|
+
if ancestor == abstract_t2:
|
|
1642
|
+
return t2
|
|
1643
|
+
return ancestor
|
|
1644
|
+
if t1 == Top_:
|
|
1645
|
+
return t2
|
|
1646
|
+
if t2 == Top_:
|
|
1647
|
+
return t1
|
|
1648
|
+
return Top_
|
|
1649
|
+
|
|
1650
|
+
@staticmethod
|
|
1651
|
+
def abstract(t: TypeConstant | TypeVariable) -> TypeConstant | TypeVariable:
|
|
1652
|
+
if isinstance(t, Pointer32):
|
|
1653
|
+
return Pointer32()
|
|
1654
|
+
if isinstance(t, Pointer64):
|
|
1655
|
+
return Pointer64()
|
|
1656
|
+
return t
|
|
1657
|
+
|
|
1658
|
+
@staticmethod
|
|
1659
|
+
def _rewrite_constraint(constraint: TypeConstraint, solutions: dict) -> TypeConstraint:
|
|
1660
|
+
if isinstance(constraint, Subtype):
|
|
1661
|
+
replaced = False
|
|
1662
|
+
if isinstance(constraint.sub_type, TypeVariable) and constraint.sub_type in solutions:
|
|
1663
|
+
sub_type = solutions[constraint.sub_type]
|
|
1664
|
+
replaced = True
|
|
1665
|
+
else:
|
|
1666
|
+
sub_type = constraint.sub_type
|
|
1667
|
+
if isinstance(constraint.super_type, TypeVariable) and constraint.super_type in solutions:
|
|
1668
|
+
super_type = solutions[constraint.super_type]
|
|
1669
|
+
replaced = True
|
|
1670
|
+
else:
|
|
1671
|
+
super_type = constraint.super_type
|
|
1672
|
+
return Subtype(sub_type, super_type) if replaced else constraint
|
|
1673
|
+
return constraint
|
|
1674
|
+
|
|
1675
|
+
def determine(
|
|
1676
|
+
self,
|
|
1677
|
+
sketches,
|
|
1678
|
+
tvs,
|
|
1679
|
+
equivalence_classes: dict[TypeVariable, TypeVariable],
|
|
1680
|
+
solution: dict,
|
|
1681
|
+
nodes: set[SketchNode] | None = None,
|
|
1682
|
+
) -> None:
|
|
1683
|
+
"""
|
|
1684
|
+
Determine C-like types from sketches.
|
|
1685
|
+
|
|
1686
|
+
:param sketches: A dictionary storing sketches for each type variable.
|
|
1687
|
+
:param solution: The dictionary storing C-like types for each type variable. Output.
|
|
1688
|
+
:param nodes: Optional. Nodes that should be considered in the sketch.
|
|
1689
|
+
:return: None
|
|
1690
|
+
"""
|
|
1691
|
+
|
|
1692
|
+
for typevar in tvs:
|
|
1693
|
+
self._solution_cache = {}
|
|
1694
|
+
self._determine(typevar, sketches[typevar], equivalence_classes, solution, nodes=nodes)
|
|
1695
|
+
|
|
1696
|
+
for v, eq in self._equivalence.items():
|
|
1697
|
+
if v not in solution and eq in solution:
|
|
1698
|
+
solution[v] = solution[eq]
|
|
1699
|
+
|
|
1700
|
+
def _determine(
|
|
1701
|
+
self,
|
|
1702
|
+
the_typevar,
|
|
1703
|
+
sketch,
|
|
1704
|
+
equivalence_classes: dict[TypeVariable, TypeVariable],
|
|
1705
|
+
solution: dict,
|
|
1706
|
+
nodes: set[SketchNode] | None = None,
|
|
1707
|
+
):
|
|
1708
|
+
"""
|
|
1709
|
+
Return the solution from sketches
|
|
1710
|
+
"""
|
|
1711
|
+
|
|
1712
|
+
if not nodes:
|
|
1713
|
+
# TODO: resolve references
|
|
1714
|
+
node = sketch.lookup(the_typevar)
|
|
1715
|
+
assert node is not None
|
|
1716
|
+
nodes = {node}
|
|
1717
|
+
|
|
1718
|
+
# consult the cache
|
|
1719
|
+
cached_results = set()
|
|
1720
|
+
for node in nodes:
|
|
1721
|
+
repr_tv = equivalence_classes.get(node.typevar, node.typevar)
|
|
1722
|
+
if repr_tv in self._solution_cache:
|
|
1723
|
+
cached_results.add(self._solution_cache[repr_tv])
|
|
1724
|
+
if len(cached_results) == 1:
|
|
1725
|
+
return next(iter(cached_results))
|
|
1726
|
+
if len(cached_results) > 1:
|
|
1727
|
+
# too many results; return TOP
|
|
1728
|
+
_l.warning("Getting multiple results when consulting the solution cache. Returning TOP.")
|
|
1729
|
+
return Top_
|
|
1730
|
+
|
|
1731
|
+
# collect all successors and the paths (labels) of this type variable
|
|
1732
|
+
path_and_successors = []
|
|
1733
|
+
last_labels = []
|
|
1734
|
+
for node in nodes:
|
|
1735
|
+
path_and_successors += self._collect_sketchnode_successors_and_paths(node, sketch)
|
|
1736
|
+
for labels, _ in path_and_successors:
|
|
1737
|
+
if labels:
|
|
1738
|
+
last_labels.append(labels[-1])
|
|
1739
|
+
|
|
1740
|
+
# now, what is this variable?
|
|
1741
|
+
result = None
|
|
1742
|
+
|
|
1743
|
+
if last_labels and all(isinstance(label, (FuncIn, FuncOut)) for label in last_labels):
|
|
1744
|
+
# create a dummy result and dump it to the cache
|
|
1745
|
+
func_type = Function([], [])
|
|
1746
|
+
result = self._pointer_class()(basetype=func_type)
|
|
1747
|
+
for node in nodes:
|
|
1748
|
+
repr_tv = equivalence_classes.get(node.typevar, node.typevar)
|
|
1749
|
+
self._solution_cache[repr_tv] = result
|
|
1750
|
+
|
|
1751
|
+
# this is a function variable
|
|
1752
|
+
func_inputs = defaultdict(set)
|
|
1753
|
+
func_outputs = defaultdict(set)
|
|
1754
|
+
|
|
1755
|
+
for labels, succ in path_and_successors:
|
|
1756
|
+
last_label = labels[-1] if labels else None
|
|
1757
|
+
|
|
1758
|
+
if isinstance(last_label, FuncIn):
|
|
1759
|
+
func_inputs[last_label.loc].add(succ)
|
|
1760
|
+
elif isinstance(last_label, FuncOut):
|
|
1761
|
+
func_outputs[last_label.loc].add(succ)
|
|
1762
|
+
else:
|
|
1763
|
+
raise RuntimeError("Unreachable")
|
|
1764
|
+
|
|
1765
|
+
input_args = []
|
|
1766
|
+
output_values = []
|
|
1767
|
+
for vals, out in [(func_inputs, input_args), (func_outputs, output_values)]:
|
|
1768
|
+
for idx in range(max(vals) + 1):
|
|
1769
|
+
if idx in vals:
|
|
1770
|
+
sol = self._determine(the_typevar, sketch, equivalence_classes, solution, nodes=vals[idx])
|
|
1771
|
+
out.append(sol)
|
|
1772
|
+
else:
|
|
1773
|
+
out.append(None)
|
|
1774
|
+
|
|
1775
|
+
# back patch
|
|
1776
|
+
func_type.params = input_args
|
|
1777
|
+
func_type.outputs = output_values
|
|
1778
|
+
|
|
1779
|
+
for node in nodes:
|
|
1780
|
+
solution[node.typevar] = result
|
|
1781
|
+
|
|
1782
|
+
elif path_and_successors:
|
|
1783
|
+
# maybe this is a pointer to a struct?
|
|
1784
|
+
if len(nodes) == 1:
|
|
1785
|
+
the_node = next(iter(nodes))
|
|
1786
|
+
if (
|
|
1787
|
+
isinstance(the_node.upper_bound, self._pointer_class())
|
|
1788
|
+
and isinstance(the_node.upper_bound.basetype, Struct)
|
|
1789
|
+
and the_node.upper_bound.basetype.name
|
|
1790
|
+
):
|
|
1791
|
+
# handle pointers to known struct types
|
|
1792
|
+
result = (
|
|
1793
|
+
the_node.lower_bound
|
|
1794
|
+
if not isinstance(the_node.lower_bound, BottomType)
|
|
1795
|
+
else the_node.upper_bound
|
|
1796
|
+
)
|
|
1797
|
+
for node in nodes:
|
|
1798
|
+
repr_tv = equivalence_classes.get(node.typevar, node.typevar)
|
|
1799
|
+
self._solution_cache[repr_tv] = result
|
|
1800
|
+
solution[node.typevar] = result
|
|
1801
|
+
return result
|
|
1802
|
+
|
|
1803
|
+
# create a dummy result and shove it into the cache
|
|
1804
|
+
struct_type = Struct(fields={})
|
|
1805
|
+
ori_result = result = self._pointer_class()(struct_type)
|
|
1806
|
+
# print(f"Creating a struct type: {struct_type} for {the_typevar}")
|
|
1807
|
+
for node in nodes:
|
|
1808
|
+
# print(f"... assigned it to {node.typevar}")
|
|
1809
|
+
repr_tv = equivalence_classes.get(node.typevar, node.typevar)
|
|
1810
|
+
self._solution_cache[repr_tv] = result
|
|
1811
|
+
|
|
1812
|
+
# this might be a struct
|
|
1813
|
+
fields = {}
|
|
1814
|
+
|
|
1815
|
+
candidate_bases = SortedDict()
|
|
1816
|
+
ptr_offs: set[int] = set()
|
|
1817
|
+
|
|
1818
|
+
for labels, _succ in path_and_successors:
|
|
1819
|
+
last_label = labels[-1] if labels else None
|
|
1820
|
+
if isinstance(last_label, HasField):
|
|
1821
|
+
# TODO: Really determine the maximum possible size of the field when MAX_POINTSTO_BITS is in use
|
|
1822
|
+
if last_label.offset not in candidate_bases:
|
|
1823
|
+
candidate_bases[last_label.offset] = set()
|
|
1824
|
+
candidate_bases[last_label.offset].add(
|
|
1825
|
+
1 if last_label.bits == MAX_POINTSTO_BITS else (last_label.bits // 8)
|
|
1826
|
+
)
|
|
1827
|
+
elif isinstance(last_label, AddN):
|
|
1828
|
+
ptr_offs.add(last_label.n)
|
|
1829
|
+
elif isinstance(last_label, SubN):
|
|
1830
|
+
ptr_offs.add(-last_label.n)
|
|
1831
|
+
|
|
1832
|
+
# determine possible bases and map each offset to its base
|
|
1833
|
+
offset_to_base = SortedDict()
|
|
1834
|
+
for start_offset, sizes in candidate_bases.items():
|
|
1835
|
+
for size in sizes:
|
|
1836
|
+
for i in range(size):
|
|
1837
|
+
access_off = start_offset + i
|
|
1838
|
+
if access_off not in offset_to_base:
|
|
1839
|
+
offset_to_base[access_off] = start_offset
|
|
1840
|
+
|
|
1841
|
+
# determine again the maximum size of each field (at each offset)
|
|
1842
|
+
offset_to_maxsize = defaultdict(int)
|
|
1843
|
+
offset_to_sizes = defaultdict(set) # we do not consider offsets to each base offset
|
|
1844
|
+
for labels, _succ in path_and_successors:
|
|
1845
|
+
last_label = labels[-1] if labels else None
|
|
1846
|
+
if isinstance(last_label, HasField):
|
|
1847
|
+
base = offset_to_base[last_label.offset]
|
|
1848
|
+
access_size = 1 if last_label.bits == MAX_POINTSTO_BITS else (last_label.bits // 8)
|
|
1849
|
+
offset_to_maxsize[base] = max(offset_to_maxsize[base], (last_label.offset - base) + access_size)
|
|
1850
|
+
offset_to_sizes[base].add(access_size)
|
|
1851
|
+
|
|
1852
|
+
array_idx_to_base = {}
|
|
1853
|
+
|
|
1854
|
+
for idx, (labels, _) in enumerate(path_and_successors):
|
|
1855
|
+
last_label = labels[-1] if labels else None
|
|
1856
|
+
if isinstance(last_label, HasField) and last_label.elem_count > 1:
|
|
1857
|
+
prev_offset = next(offset_to_base.irange(maximum=last_label.offset, reverse=True))
|
|
1858
|
+
array_idx_to_base[idx] = offset_to_base[prev_offset]
|
|
1859
|
+
|
|
1860
|
+
node_by_offset = defaultdict(set)
|
|
1861
|
+
|
|
1862
|
+
for idx, (labels, succ) in enumerate(path_and_successors):
|
|
1863
|
+
last_label = labels[-1] if labels else None
|
|
1864
|
+
if isinstance(last_label, HasField):
|
|
1865
|
+
if idx in array_idx_to_base:
|
|
1866
|
+
node_by_offset[array_idx_to_base[idx]].add(succ)
|
|
1867
|
+
else:
|
|
1868
|
+
node_by_offset[last_label.offset].add(succ)
|
|
1869
|
+
|
|
1870
|
+
sorted_offsets: list[int] = sorted(node_by_offset)
|
|
1871
|
+
for i in range(len(sorted_offsets)): # pylint:disable=consider-using-enumerate
|
|
1872
|
+
offset = sorted_offsets[i]
|
|
1873
|
+
|
|
1874
|
+
child_nodes = node_by_offset[offset]
|
|
1875
|
+
sol = self._determine(the_typevar, sketch, equivalence_classes, solution, nodes=child_nodes)
|
|
1876
|
+
if isinstance(sol, TopType) and offset in offset_to_sizes:
|
|
1877
|
+
# make it an array if possible
|
|
1878
|
+
elem_size = min(offset_to_sizes[offset])
|
|
1879
|
+
array_size = offset_to_maxsize[offset]
|
|
1880
|
+
if array_size % elem_size != 0:
|
|
1881
|
+
# fall back to byte_t
|
|
1882
|
+
elem_size = 1
|
|
1883
|
+
elem_type = int_type(elem_size * 8)
|
|
1884
|
+
sol = elem_type if array_size == elem_size else Array(elem_type, array_size // elem_size)
|
|
1885
|
+
fields[offset] = sol
|
|
1886
|
+
|
|
1887
|
+
if len(fields) >= 2:
|
|
1888
|
+
# we only trigger this logic when there are at least two identified fields, which means it's going to
|
|
1889
|
+
# be either a struct or an array
|
|
1890
|
+
# see TestDecompiler.test_simple_strcpy for an example with only one member in fields and a +1 access,
|
|
1891
|
+
# due to ptr arithmetic
|
|
1892
|
+
if any(off < 0 for off in ptr_offs):
|
|
1893
|
+
# we see references to negative offsets
|
|
1894
|
+
# we resolve this guy as a pointer to an Int8 type
|
|
1895
|
+
result = self._pointer_class()(Int8_)
|
|
1896
|
+
else:
|
|
1897
|
+
for off in ptr_offs:
|
|
1898
|
+
if off not in fields:
|
|
1899
|
+
# missing field at this offset
|
|
1900
|
+
fields[off] = Int8_ # not sure how it's accessed
|
|
1901
|
+
|
|
1902
|
+
if not fields:
|
|
1903
|
+
result = Top_
|
|
1904
|
+
for node in nodes:
|
|
1905
|
+
repr_tv = equivalence_classes.get(node.typevar, node.typevar)
|
|
1906
|
+
self._solution_cache[repr_tv] = result
|
|
1907
|
+
solution[node.typevar] = result
|
|
1908
|
+
elif any(off < 0 for off in fields) or any(fld is Bottom_ for fld in fields.values()):
|
|
1909
|
+
result = self._pointer_class()(Bottom_)
|
|
1910
|
+
for node in nodes:
|
|
1911
|
+
repr_tv = equivalence_classes.get(node.typevar, node.typevar)
|
|
1912
|
+
self._solution_cache[repr_tv] = result
|
|
1913
|
+
solution[node.typevar] = result
|
|
1914
|
+
for tv in list(solution):
|
|
1915
|
+
solution[tv] = self._rewrite_typeconstant_with_replacements(solution[tv], {ori_result: result})
|
|
1916
|
+
else:
|
|
1917
|
+
# back-patch
|
|
1918
|
+
struct_type.fields = fields
|
|
1919
|
+
for node in nodes:
|
|
1920
|
+
solution[node.typevar] = result
|
|
1921
|
+
|
|
1922
|
+
if not path_and_successors or result in {Top_, None}:
|
|
1923
|
+
# this is probably a primitive variable
|
|
1924
|
+
lower_bound = Bottom_
|
|
1925
|
+
upper_bound = Top_
|
|
1926
|
+
|
|
1927
|
+
node_sizes = set()
|
|
1928
|
+
for node in nodes:
|
|
1929
|
+
node_size = node.size
|
|
1930
|
+
if node_size is not None:
|
|
1931
|
+
node_sizes.add(node_size)
|
|
1932
|
+
if len(node_sizes) > 1:
|
|
1933
|
+
# multi-sized reads - cannot converge to a reasonable type
|
|
1934
|
+
result = Bottom_
|
|
1935
|
+
else:
|
|
1936
|
+
for node in nodes:
|
|
1937
|
+
lower_bound = self.join(lower_bound, node.lower_bound)
|
|
1938
|
+
upper_bound = self.meet(upper_bound, node.upper_bound)
|
|
1939
|
+
result = lower_bound if not isinstance(lower_bound, BottomType) else upper_bound
|
|
1940
|
+
|
|
1941
|
+
for node in nodes:
|
|
1942
|
+
repr_tv = equivalence_classes.get(node.typevar, node.typevar)
|
|
1943
|
+
self._solution_cache[repr_tv] = result
|
|
1944
|
+
solution[node.typevar] = result
|
|
1945
|
+
|
|
1946
|
+
# import pprint
|
|
1947
|
+
|
|
1948
|
+
# print("Solution")
|
|
1949
|
+
# pprint.pprint(result)
|
|
1950
|
+
return result
|
|
1951
|
+
|
|
1952
|
+
@staticmethod
|
|
1953
|
+
def _collect_sketchnode_successors_and_paths(
|
|
1954
|
+
node: SketchNodeBase, sketch: Sketch
|
|
1955
|
+
) -> list[tuple[list[BaseLabel], SketchNodeBase]]:
|
|
1956
|
+
"""
|
|
1957
|
+
Collect all paths that go from `node` to its immediate next successors, following Load/Store labels.
|
|
1958
|
+
"""
|
|
1959
|
+
paths = []
|
|
1960
|
+
visited: set[SketchNodeBase] = set()
|
|
1961
|
+
queue: list[tuple[list[BaseLabel], SketchNodeBase]] = [([], node)]
|
|
1962
|
+
|
|
1963
|
+
while queue:
|
|
1964
|
+
curr_labels, curr_node = queue.pop(0)
|
|
1965
|
+
if curr_node in visited:
|
|
1966
|
+
continue
|
|
1967
|
+
visited.add(curr_node)
|
|
1968
|
+
|
|
1969
|
+
out_edges = sketch.graph.out_edges(curr_node, data=True)
|
|
1970
|
+
for _, succ, data in sorted(out_edges, key=lambda x: str(x[1])):
|
|
1971
|
+
if isinstance(succ, RecursiveRefNode):
|
|
1972
|
+
ref = succ
|
|
1973
|
+
succ: SketchNode | None = sketch.lookup(succ.target) # type: ignore
|
|
1974
|
+
if succ is None:
|
|
1975
|
+
# failed to resolve...
|
|
1976
|
+
_l.warning(
|
|
1977
|
+
"Failed to resolve reference node to a real sketch node for type variable %s", ref.target
|
|
1978
|
+
)
|
|
1979
|
+
continue
|
|
1980
|
+
label = data["label"]
|
|
1981
|
+
if isinstance(label, ConvertTo):
|
|
1982
|
+
# drop conv labels for now
|
|
1983
|
+
continue
|
|
1984
|
+
if isinstance(label, IsArray):
|
|
1985
|
+
continue
|
|
1986
|
+
new_labels = [*curr_labels, label]
|
|
1987
|
+
succ: SketchNode
|
|
1988
|
+
if isinstance(succ.typevar, DerivedTypeVariable) and isinstance(succ.typevar.labels[-1], (Load, Store)):
|
|
1989
|
+
queue.append((new_labels, succ))
|
|
1990
|
+
else:
|
|
1991
|
+
paths.append((new_labels, succ))
|
|
1992
|
+
|
|
1993
|
+
return paths
|
|
1994
|
+
|
|
1995
|
+
def _pointer_class(self) -> type[Pointer32] | type[Pointer64]:
|
|
1996
|
+
if self.bits == 32:
|
|
1997
|
+
return Pointer32
|
|
1998
|
+
if self.bits == 64:
|
|
1999
|
+
return Pointer64
|
|
2000
|
+
raise NotImplementedError(f"Unsupported bits {self.bits}")
|
|
2001
|
+
|
|
2002
|
+
@staticmethod
|
|
2003
|
+
def dump_constraint_graph(graph: networkx.DiGraph, filename: str) -> None:
|
|
2004
|
+
"""
|
|
2005
|
+
Dump the constraint graph to a file.
|
|
2006
|
+
"""
|
|
2007
|
+
from networkx.drawing.nx_agraph import write_dot # pylint:disable=import-outside-toplevel
|
|
2008
|
+
|
|
2009
|
+
write_dot(graph, filename)
|