From c7639a64a91b3e88fb66ab51951e80aaff83a972 Mon Sep 17 00:00:00 2001 From: Henny Sipma Date: Wed, 3 Jun 2026 12:17:03 -0700 Subject: [PATCH 1/4] JSON:add json result for side-effect variable --- chb/app/CHVersion.py | 2 +- chb/invariants/VConstantValueVariable.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/chb/app/CHVersion.py b/chb/app/CHVersion.py index 23f57e87..06af1529 100644 --- a/chb/app/CHVersion.py +++ b/chb/app/CHVersion.py @@ -1,3 +1,3 @@ -chbversion: str = "0.3.0-20260527" +chbversion: str = "0.3.0-20260603" minimum_required_chb_version = "0.6.0_20260527" diff --git a/chb/invariants/VConstantValueVariable.py b/chb/invariants/VConstantValueVariable.py index b8304667..e998202b 100644 --- a/chb/invariants/VConstantValueVariable.py +++ b/chb/invariants/VConstantValueVariable.py @@ -842,6 +842,18 @@ def call_target(self) -> CallTarget: else: raise UF.CHBError("Side-effect value does not have a call target.") + def to_json_result(self) -> JSONResult: + content: Dict[str, Any] = {} + content["kind"] = "se" + content["callsite"] = self.callsite + if self.has_call_target(): + content["calltarget"] = str(self.call_target()) + else: + content["calltarget"] = "none" + content["description"] = self.argument_desc + content["txtrep"] = self.__str__() + return JSONResult("auxvariable", content, "ok") + def __str__(self) -> str: if self.has_call_target(): return 'se_' + str(self.call_target()) + '_' + self.argument_desc From c9c5d4d3068c52ef1ce91298b7ad7b0be37d38cf Mon Sep 17 00:00:00 2001 From: Henny Sipma Date: Wed, 3 Jun 2026 16:37:32 -0700 Subject: [PATCH 2/4] REPORT: filter out non-stack arguments in patch record creation --- chb/cmdline/reportcmds.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/chb/cmdline/reportcmds.py b/chb/cmdline/reportcmds.py index 7b78a8c3..08410445 100644 --- a/chb/cmdline/reportcmds.py +++ b/chb/cmdline/reportcmds.py @@ -1458,6 +1458,8 @@ def include_target(target: 'CallTarget') -> bool: # and add it to the patch records. inter_fname, inter_func, inter_instr = inter argument = inter_instr.call_arguments[dstarg_index] + if not argument.is_stack_address: + continue stackframe = inter_func.stackframe dstoffset = argument.stack_address_offset() buffersize, sizeorigin = calculate_buffer_size(stackframe, dstoffset, instr) From fedae868ebeb8541d1f66fa2535f3aff6f4fd830 Mon Sep 17 00:00:00 2001 From: Henny Sipma Date: Wed, 3 Jun 2026 16:46:17 -0700 Subject: [PATCH 3/4] CMD: add include_callees relational-prepare command --- chb/app/AppResultMetrics.py | 7 +++++++ chb/cmdline/relationalcmds.py | 23 ++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/chb/app/AppResultMetrics.py b/chb/app/AppResultMetrics.py index 565f003a..f907fa16 100644 --- a/chb/app/AppResultMetrics.py +++ b/chb/app/AppResultMetrics.py @@ -95,6 +95,13 @@ def fns_included(self) -> List[str]: else: return addrs.split(",") + @property + def include_callees(self) -> bool: + incnode = self.xnode.find("fns-included") + if incnode is None: + return False + return (incnode.get("include-callees", "no") == "yes") + @property def fns_excluded(self) -> List[str]: excnode = self.xnode.find("fns-excluded") diff --git a/chb/cmdline/relationalcmds.py b/chb/cmdline/relationalcmds.py index 158a76ba..9807603e 100644 --- a/chb/cmdline/relationalcmds.py +++ b/chb/cmdline/relationalcmds.py @@ -4,7 +4,7 @@ # ------------------------------------------------------------------------------ # The MIT License (MIT) # -# Copyright (c) 2021-2025 Aarno Labs, LLC +# Copyright (c) 2021-2026 Aarno Labs, LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -275,17 +275,25 @@ def relational_prepare_command(args: argparse.Namespace) -> NoReturn: # Determine functions analyzed in original binary fns_include: List[str] = [] fns_exclude: List[str] = [] + include_callees: bool = False app1 = UC.get_app(path1, xfile1, xinfo1) stats1 = app1.result_metrics fncount1 = stats1.function_count if len(stats1.fns_included) > 0: fns_include = stats1.fns_included - UC.print_status_update( - "Only analyzing " - + str(len(fns_include)) - + " out of " - + str(fncount1) - + " functions") + include_callees = stats1.include_callees + if include_callees: + UC.print_status_update( + "Analyzing " + + str(len(fns_include)) + + " functions and their callees") + else: + UC.print_status_update( + "Only analyzing " + + str(len(fns_include)) + + " out of " + + str(fncount1) + + " functions") elif len(stats1.fns_excluded) > 0: fns_exclude = stats1.fns_excluded UC.print_status_update( @@ -306,6 +314,7 @@ def relational_prepare_command(args: argparse.Namespace) -> NoReturn: ifilenames=ifilenames, fns_include=fns_include, fns_exclude=fns_exclude, + fns_include_callees=include_callees, use_ssa=xssa, thumb=xcomparison.is_thumb) From 646682f6f474757ab537b0afd2a77a5fd84e9f78 Mon Sep 17 00:00:00 2001 From: Henny Sipma Date: Wed, 3 Jun 2026 21:47:28 -0700 Subject: [PATCH 4/4] REPORT: undo earlier commit --- chb/cmdline/reportcmds.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/chb/cmdline/reportcmds.py b/chb/cmdline/reportcmds.py index 0166e9e1..5c0015ef 100644 --- a/chb/cmdline/reportcmds.py +++ b/chb/cmdline/reportcmds.py @@ -1458,8 +1458,6 @@ def include_target(target: 'CallTarget') -> bool: # and add it to the patch records. inter_fname, inter_func, inter_instr = inter argument = inter_instr.call_arguments[dstarg_index] - if not argument.is_stack_address: - continue stackframe = inter_func.stackframe # Only analyze calls that involve stack arguments. if not argument.is_stack_address: