@@ -303,6 +303,23 @@ symbolic_operand_point(EA,Imm_index,-1,"immediate is bitmask"):-
303303 instruction_get_operation(EA,Operation),
304304 arch.logic_operation(Operation).
305305
306+ // Heuristic: treat values with >=20 trailing zero bits (0xFFFFF) as bitmasks.
307+ //
308+ // This threshold is empirical, not architectural. It was chosen to avoid
309+ // misclassifying large immediates observed in bgpd (e.g., 0x800000)
310+ // as addresses, while remaining more conservative than a 16-bit cutoff.
311+ // Using 24 trailing zeros would miss this case; using 16 would increase
312+ // false positives. If new binaries show misclassification in either direction,
313+ // this threshold should be revisited.
314+ //
315+ symbolic_operand_point(EA,Imm_index,-1,"immediate may be bitmask"):-
316+ symbolic_operand_candidate(EA,Imm_index,_,_),
317+ instruction_get_op(EA,Imm_index,Op),
318+ op_immediate(Op,Imm,_),
319+ !defined_symbol(as(Imm,address),_,_,_,_,_,_,_,_),
320+ !loaded_section(as(Imm,address),_,_),
321+ 0 = (Imm band 0xFFFFF).
322+
306323symbolic_operand_point(EA,Imm_index,-2,"point to exception section"):-
307324 symbolic_operand_candidate(EA,Imm_index,Dest,_),
308325 exception_section(Name),
@@ -451,6 +468,21 @@ address_in_data_is_printable(EA):-
451468 address_in_data(EA,_),
452469 EAString <= EA, EA <= End - Pt_size.
453470
471+ /**
472+ The address appearing at 'EA' overlaps with a potential
473+ `ascii_string` and therefore more likely to be spurious.
474+ */
475+ .decl address_in_data_overlaps_string(EA:address, EAString:address)
476+
477+ address_in_data_overlaps_string(EA, EAString):-
478+ ascii_string(EAString,End),
479+ address_in_data(EA,_),
480+ (
481+ EAString <= EA, EA < End;
482+ arch.pointer_size(Pt_size),
483+ EAString < EA+Pt_size, EA+Pt_size <= End
484+ ).
485+
454486// address_in_data considers anything that points to the code region
455487// this refinement restricts that to the beginning of the final blocks
456488.decl address_in_data_refined(EA:address,Val:address)
@@ -544,6 +576,23 @@ string_candidate(EA,End,"ascii"):-
544576 EA >= DataBeg,
545577 End <= DataEnd.
546578
579+ /**
580+ String at EA is followed by another string at Next.
581+ */
582+ .decl subsequent_string_candidate(EA:address,Next:address)
583+
584+ subsequent_string_candidate(EA,Next):-
585+ string_candidate(EA,End,_),
586+ string_candidate(Next,_,_),
587+ End <= Next,
588+ (
589+ End = Next
590+ ;
591+ 0 = count : {string_candidate(Begin,_,_), Begin >= End, Begin < Next},
592+ Next - End < 8,
593+ padding_block_limit(Next)
594+ ).
595+
547596/**
548597String candidate refinement projects candidate string references onto a compound
549598domain of "ascii" or "string" typed data objects, where "string" typed objects
@@ -798,6 +847,29 @@ data_object_point(EA,Pt_size,"symbol",2,"aligned"):-
798847 data_object_candidate(EA,Pt_size,"symbol"),
799848 EA % Pt_size = 0.
800849
850+ data_object_point(EA,Pt_size,"symbol",-2,"potentially bitmask"):-
851+ data_object_candidate(EA,Pt_size,"symbol"),
852+ EA % Pt_size = 0,
853+ address_in_data_refined(EA,Dest),
854+ !defined_symbol(Dest,_,_,_,_,_,_,_,_),
855+ 0 = (Dest band 0xFFFFF).
856+
857+ data_object_point(EA,Pt_size,"symbol",-2,"printerable address: likely spurious"):-
858+ data_object_candidate(EA,Pt_size,"symbol"),
859+ EA % Pt_size = 0,
860+ address_in_data_is_printable(EA),
861+ address_in_data_refined(EA,Dest),
862+ !defined_symbol(Dest,_,_,_,_,_,_,_,_).
863+
864+ data_object_point(EA,Pt_size,"symbol",-1,"overlaps string: likely spurious"):-
865+ data_object_candidate(EA,Pt_size,"symbol"),
866+ EA % Pt_size = 0,
867+ address_in_data_overlaps_string(EA,EAString),
868+ ascii_string(EAString,End),
869+ End - EAString > 4,
870+ address_in_data_refined(EA,Dest),
871+ !defined_symbol(Dest,_,_,_,_,_,_,_,_).
872+
801873data_object_point(EA,Pt_size,"symbol",4,"point-to-boundary-sym"):-
802874 data_object_candidate(EA,Pt_size,"symbol"),
803875 address_in_data_refined(EA,Dest),
@@ -852,6 +924,11 @@ data_object_point(EA,Size,"string",1,"string that has reference"):-
852924 code(Code),
853925 data_limit(EA).
854926
927+ data_object_point(EA,Size,"string",1,"string has string neighbors"):-
928+ data_object_candidate(EA,Size,"string"),
929+ subsequent_string_candidate(EA,_),
930+ subsequent_string_candidate(_,EA).
931+
855932// data access negative heuristic
856933data_object_point(EA,Size,"other",4,"data access"):-
857934 data_object_candidate(EA,Size,"other"),
0 commit comments