panda/
taint.rs

1//! Taint analysis API
2//!
3//! This module provides a series of helpers designed for using the [`taint2`] PANDA plugin in order
4//! to perform [dynamic taint analysis] in order to help track
5//!
6//! [`taint2`]: https://github.com/panda-re/panda/tree/dev/panda/plugins/taint2
7//! [dynamic taint analysis]: https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.681.4094&rep=rep1&type=pdf
8//!
9//! ## Example
10//!
11//! ```no_run
12//! use panda::taint;
13//! use panda::regs::Reg;
14//!
15//! // show all registers are untainted
16//! for reg in [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX] {
17//!     println!("{:?} is tained? {:?}", reg, taint::check_reg(reg));
18//! }
19//!
20//! println!("Tainting RAX...");
21//! taint::label_reg(Reg::RAX, 1);
22//!
23//! // ...
24//!
25//! // show taint has propagated to any values effected by the opterations performed on RAX
26//! for reg in [Reg::RAX, Reg::RBX, Reg::RCX, Reg::RDX] {
27//!     println!("{:?} is tained? {:?}", reg, taint::check_reg(reg));
28//! }
29//! ```
30//!
31//! ([Full Example](https://github.com/panda-re/panda-rs/blob/master/panda-rs/examples/unicorn_taint.rs))
32
33use crate::api::regs::Reg;
34use crate::plugin_import;
35use crate::sys::{target_ptr_t, CPUState};
36
37use std::collections::HashSet;
38use std::ops::Range;
39use std::os::raw::{c_int, c_long, c_void};
40use std::ptr;
41use std::sync::Once;
42
43plugin_import! {
44    /// Direct access to the taint2 C API when direct use is needed
45    static TAINT: Taint = extern "taint2" {
46        fn taint2_enable_taint();
47        fn taint2_enable_tainted_pointer();
48        fn taint2_enabled() -> bool;
49
50        fn taint2_label_addr(a: Addr, offset: c_int, label: u32);
51        fn taint2_label_ram(ram_offset: u64, label: u32);
52        fn taint2_label_reg(reg_num: c_int, offset: c_int, label: u32);
53        fn taint2_label_io(ia: u64, label: u32);
54        fn taint2_label_ram_additive(ram_offset: u64, label: u32);
55        fn taint2_label_reg_additive(reg_num: c_int, offset: c_int, label: u32);
56        fn taint2_label_io_additive(ia: u64, label: u32);
57        fn taint2_add_taint_ram_pos(cpu: &mut CPUState, addr: u64, length: u32, start_label: u32);
58        fn taint2_add_taint_ram_single_label(cpu: &mut CPUState, addr: u64, length: u32, label: c_long);
59
60        fn taint2_delete_ram(ram_offset: u64);
61        fn taint2_delete_reg(reg_num: c_int, offset: c_int);
62        fn taint2_delete_io(ia: u64);
63
64        fn taint2_query_pandalog(addr: Addr, offset: u32) -> *mut c_void;
65        fn pandalog_taint_query_free(tq: *mut c_void);
66
67        fn taint2_query(addr: Addr) -> u32;
68        fn taint2_query_reg(reg_num: c_int, offset: c_int) -> u32;
69        fn taint2_query_ram(ram_offset: u64) -> u32;
70        fn taint2_query_laddr(la: u64, off: u64) -> u32;
71        fn taint2_query_io(ia: u64) -> u32;
72        fn taint2_query_llvm(reg_num: c_int, offset: c_int) -> u32;
73
74        fn taint2_query_set_a(a: Addr, out: &mut *mut u32, outsz: &mut u32) -> u32;
75
76        fn taint2_query_set(a: Addr, out: *mut u32);
77        fn taint2_query_set_ram(ram_offset: u64, out: *mut u32);
78        fn taint2_query_set_reg(reg_num: c_int, offset: c_int, out: *mut u32);
79        fn taint2_query_set_io(ia: u64, out: *mut u32);
80
81        fn taint2_query_tcn(a: Addr) -> u32;
82        fn taint2_query_tcn_ram(ram_offset: u64) -> u32;
83        fn taint2_query_tcn_reg(reg_num: c_int, offset: c_int) -> u32;
84        fn taint2_query_tcn_io(ia: u64) -> u32;
85        fn taint2_query_tcn_llvm(reg_num: c_int, offset: c_int) -> u32;
86
87        fn taint2_query_cb_mask(a: Addr, size: u8) -> u64;
88
89        fn taint2_labelset_addr_iter(addr: Addr, app: LabelSetVisitorRawFn, stuff: *mut c_void);
90        fn taint2_labelset_ram_iter(ram_offset: u64, app: LabelSetVisitorRawFn, stuff: *mut c_void);
91        fn taint2_labelset_reg_iter(reg_num: c_int, offset: c_int, app: LabelSetVisitorRawFn, stuff: *mut c_void);
92        fn taint2_labelset_io_iter(ia: u64, app: LabelSetVisitorRawFn, stuff: *mut c_void);
93        fn taint2_labelset_llvm_iter(reg_num: c_int, offset: c_int, app: LabelSetVisitorRawFn, stuff: *mut c_void);
94
95        fn taint2_num_labels_applied() -> u32;
96
97        fn taint2_track_taint_state();
98
99        fn taint2_query_results_iter(qr: &mut QueryResult);
100        fn taint2_query_result_next(qr: &mut QueryResult, done: &mut bool) -> u32;
101        fn taint2_query_laddr_full(reg_num: u64, offset: u64, qr: &mut QueryResult);
102        fn taint2_query_reg_full(reg_num: u32, offset: u32, qr: &mut QueryResult);
103        fn taint2_query_ram_full(addr: u64, qr: &mut QueryResult);
104    };
105}
106
107pub type LabelSetVisitorRawFn = extern "C" fn(u32, *mut c_void) -> c_int;
108
109#[derive(Clone, Copy)]
110#[repr(C)]
111pub union ValueUnion {
112    pub ha: u64,
113    pub ma: u64,
114    pub ia: u64,
115    pub pa: u64,
116    pub la: u64,
117    pub gr: u64,
118    pub gs: u64,
119    pub ua: u64,
120    pub con: u64,
121    pub ret: u64,
122}
123
124#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
125#[repr(C)]
126#[allow(non_camel_case_types)]
127pub enum AddrType {
128    HADDR,
129    MADDR,
130    IADDR,
131    PADDR,
132    LADDR,
133    GREG,
134    GSPEC,
135    UNK,
136    CONST,
137    RET,
138    ADDR_LAST,
139}
140
141#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
142#[repr(C)]
143#[allow(non_camel_case_types)]
144pub enum AddrFlag {
145    IRRELEVANT = 5,
146    EXCEPTION = 1,
147    READLOG,
148    FUNCARG,
149}
150
151#[derive(Clone, Copy)]
152#[repr(C)]
153pub struct Addr {
154    pub typ: AddrType,
155    pub val: ValueUnion,
156    pub off: u16,
157    pub flag: AddrFlag,
158}
159
160static TAINT_ENABLE: Once = Once::new();
161
162/// Ensure the taint system is enabled
163///
164/// Note: most functions call this internally, check the docs for individual helpers, as in most
165/// cases you don't need to call this directly unless you want to enable the taint system earlier
166/// than directly before using it.
167///
168/// On subsequent calls, this function will have the same performance characteristics as
169/// [`Once::call_once`](https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once).
170pub fn enable() {
171    TAINT_ENABLE.call_once(|| {
172        TAINT.taint2_enable_taint();
173    })
174}
175
176/// Check if the taint system is enabled
177pub fn is_enabled() -> bool {
178    TAINT.taint2_enabled()
179}
180
181/// Enable pointer tainting rules. May result in overtainting.
182pub fn enable_tainted_pointer() {
183    TAINT.taint2_enable_tainted_pointer()
184}
185
186/// Apply a 32-bit taint label to a given register.
187///
188/// ## Example
189///
190/// ```no_run
191/// use panda::taint;
192/// use panda::regs::Reg;
193///
194/// // Select register by enum for compile-time guarantees
195/// taint::label_reg(Reg::RAX, 1);
196///
197/// // Select register by string when needed
198/// taint::label_reg("rax", 1);
199/// ```
200///
201/// If a register is not supported by the [`Reg`] API, either make an issue or use
202/// [`taint2_label_reg`] directly. (example: `TAINT.taint2_label_reg(reg_num, 0, label)`)
203///
204/// [`taint2_label_reg`]: Taint::taint2_label_reg
205///
206/// **Note**: This will enable taint if not already enabled.
207pub fn label_reg(register: impl Into<Reg>, label: u32) {
208    let reg = register.into() as c_int;
209    enable();
210    for i in 0..std::mem::size_of::<target_ptr_t>() {
211        TAINT.taint2_label_reg(reg, i as c_int, label);
212    }
213}
214
215/// Add a 32-bit taint label to a given register. Any previous taint labels on the same register are not removed.
216///
217/// ## Example
218///
219/// ```no_run
220/// use panda::taint;
221/// use panda::regs::Reg;
222///
223/// // Select register by enum for compile-time guarantees
224/// taint::label_reg_additive(Reg::RAX, 1);
225///
226/// // Select register by string when needed
227/// taint::label_reg_additive("rax", 1);
228/// ```
229///
230/// If a register is not supported by the [`Reg`] API, either make an issue or use
231/// [`taint2_label_reg_additive`] directly. (example: `TAINT.taint2_label_reg_additive(reg_num, 0, label)`)
232///
233/// [`taint2_label_reg_additive`]: Taint::taint2_label_reg_additive
234///
235/// **Note**: This will enable taint if not already enabled.
236pub fn label_reg_additive(register: impl Into<Reg>, label: u32) {
237    let reg = register.into() as c_int;
238    enable();
239    for i in 0..std::mem::size_of::<target_ptr_t>() {
240        TAINT.taint2_label_reg_additive(reg, i as c_int, label);
241    }
242}
243
244/// Apply a 32-bit taint label to a specific byte of a given register.
245///
246/// ## Panics
247///
248/// This function panics if `byte_offset` is greater than or equal to the size of the register.
249///
250/// ## Example
251///
252/// ```no_run
253/// use panda::taint;
254/// use panda::regs::Reg;
255///
256/// // Select register by enum for compile-time guarantees
257/// taint::label_reg_byte(Reg::RAX, 0, 1);
258///
259/// // Select register by string when needed
260/// taint::label_reg_byte("rax", 0, 1);
261/// ```
262///
263/// **Note**: This will enable taint if not already enabled.
264pub fn label_reg_byte(register: impl Into<Reg>, byte_offset: usize, label: u32) {
265    assert!(byte_offset < std::mem::size_of::<target_ptr_t>());
266
267    let reg = register.into() as c_int;
268    enable();
269    TAINT.taint2_label_reg(reg, byte_offset as c_int, label);
270}
271
272/// Apply a 32-bit taint label to a specific byte of a given register. Any previous taint labels on the same register
273/// byte are not removed.
274///
275/// ## Panics
276///
277/// This function panics if `byte_offset` is greater than or equal to the size of the register.
278///
279/// ## Example
280///
281/// ```no_run
282/// use panda::taint;
283/// use panda::regs::Reg;
284///
285/// // Select register by enum for compile-time guarantees
286/// taint::label_reg_byte_additive(Reg::RAX, 0, 1);
287///
288/// // Select register by string when needed
289/// taint::label_reg_byte_additive("rax", 0, 1);
290/// ```
291///
292/// **Note**: This will enable taint if not already enabled.
293pub fn label_reg_byte_additive(register: impl Into<Reg>, byte_offset: usize, label: u32) {
294    assert!(byte_offset < std::mem::size_of::<target_ptr_t>());
295
296    let reg = register.into() as c_int;
297    enable();
298    TAINT.taint2_label_reg_additive(reg, byte_offset as c_int, label);
299}
300
301/// Apply a 32-bit taint label to a given byte in RAM.
302///
303/// ## Example
304///
305/// ```no_run
306/// use panda::taint;
307///
308/// // taint the byte at address 0xfffffff01c5 with a label of 4
309/// taint::label_ram(0xfffffff01c5, 4);
310/// ```
311///
312/// **Note**: This will enable taint if not already enabled.
313pub fn label_ram(addr: target_ptr_t, label: u32) {
314    enable();
315    TAINT.taint2_label_ram(addr as u64, label)
316}
317
318/// Add a 32-bit taint label to a given byte in RAM. Any previous taint labels on the same byte are not removed.
319///
320/// ## Example
321///
322/// ```no_run
323/// use panda::taint;
324///
325/// // Add a new taint label `4` to the byte at address 0xfffffff01c5
326/// taint::label_ram_additive(0xfffffff01c5, 4);
327/// ```
328///
329/// **Note**: This will enable taint if not already enabled.
330pub fn label_ram_additive(addr: target_ptr_t, label: u32) {
331    enable();
332    TAINT.taint2_label_ram_additive(addr as u64, label);
333}
334
335/// Apply a 32-bit taint label to a range of bytes in RAM.
336///
337/// ## Example
338///
339/// ```no_run
340/// use panda::taint;
341/// use panda::prelude::*;
342///
343/// // Select register by enum for compile-time guarantees
344/// let start = 0xfffffff01c4;
345/// let end = start + std::mem::size_of::<target_ptr_t>();
346/// taint::label_ram(start..end, 4);
347/// ```
348///
349/// **Note**: This will enable taint if not already enabled.
350pub fn label_ram_range(addr_range: Range<target_ptr_t>, label: u32) {
351    enable();
352    for addr in addr_range {
353        TAINT.taint2_label_ram(addr as u64, label);
354    }
355}
356
357/// Add a 32-bit taint label to a range of bytes in RAM. Any previous taint labels on the same range of bytes are not
358/// removed.
359///
360/// ## Example
361///
362/// ```no_run
363/// use panda::taint;
364/// use panda::prelude::*;
365///
366/// // Select register by enum for compile-time guarantees
367/// let start = 0xfffffff01c4;
368/// let end = start + std::mem::size_of::<target_ptr_t>();
369/// taint::label_ram_range_additive(start..end, 4);
370/// ```
371///
372/// **Note**: This will enable taint if not already enabled.
373pub fn label_ram_range_additive(addr_range: Range<target_ptr_t>, label: u32) {
374    enable();
375    for addr in addr_range {
376        TAINT.taint2_label_ram_additive(addr as u64, label);
377    }
378}
379
380/// Removes all taint labels on all bytes of a given register.
381///
382/// This function effectively does nothing if taint is not enabled.
383pub fn unlabel_reg(register: impl Into<Reg>) {
384    if !TAINT_ENABLE.is_completed() {
385        return;
386    }
387
388    let reg = register.into() as c_int;
389    for i in 0..std::mem::size_of::<target_ptr_t>() {
390        TAINT.taint2_delete_reg(reg, i as c_int);
391    }
392}
393
394/// Removes all taint labels on a specific byte of a given register.
395///
396/// This function effectively does nothing if taint is not enabled.
397///
398/// ## Panics
399///
400/// This function panics if `byte_offset` is greater than or equal to the size of the register.
401pub fn unlabel_reg_byte(register: impl Into<Reg>, byte_offset: usize) {
402    assert!(byte_offset < std::mem::size_of::<target_ptr_t>());
403
404    if !TAINT_ENABLE.is_completed() {
405        return;
406    }
407
408    let reg = register.into() as c_int;
409    TAINT.taint2_delete_reg(reg, byte_offset as c_int);
410}
411
412/// Removes all taint labels on a given byte in RAM.
413///
414/// This function effectively does nothing if taint is not enabled.
415pub fn unlabel_ram(addr: target_ptr_t) {
416    if !TAINT_ENABLE.is_completed() {
417        return;
418    }
419
420    TAINT.taint2_delete_ram(addr as u64);
421}
422
423/// Removes all taint labels on a range of bytes in RAM.
424///
425/// This function effectively does nothing if taint is not enabled.
426pub fn unlabel_ram_range(addr_range: Range<target_ptr_t>) {
427    if !TAINT_ENABLE.is_completed() {
428        return;
429    }
430
431    for addr in addr_range {
432        TAINT.taint2_delete_ram(addr as u64);
433    }
434}
435
436/// Check if a register is tainted by any label
437///
438/// ## Example
439///
440/// ```no_run
441/// use panda::taint;
442/// use panda::regs::Reg;
443///
444/// taint::label_reg(Reg::RAX);
445///
446/// if taint::check_reg(Reg::RAX) {
447///     println!("RAX is tainted by some label");
448/// }
449/// ```
450pub fn check_reg(reg: impl Into<Reg>) -> bool {
451    let reg_num = reg.into() as c_int;
452    check_reg_num(reg_num)
453}
454
455/// Check if a specific byte of a register is tainted by any label
456///
457/// ## Panics
458///
459/// This function panics if `byte_offset` is greater than or equal to the size of the register.
460///
461/// ## Example
462///
463/// ```no_run
464/// use panda::taint;
465/// use panda::regs::Reg;
466///
467/// taint::label_reg_byte(Reg::RAX, 1, 1);
468///
469/// if taint::check_reg_byte(Reg::RAX, 1) {
470///     println!("RAX[1] is tainted by some label");
471/// }
472/// ```
473pub fn check_reg_byte(reg: impl Into<Reg>, byte_offset: usize) -> bool {
474    assert!(byte_offset < std::mem::size_of::<target_ptr_t>());
475
476    let reg_num = reg.into() as c_int;
477    check_reg_num_byte(reg_num, byte_offset)
478}
479
480/// Check if a register is tainted by any label, by the register number
481///
482/// ### Notes
483///
484/// * When your given register is supported in the [`Reg`] API, use [`check_reg`]
485/// * If taint has not been enabled by **your** plugin, this will return false
486pub fn check_reg_num(reg_num: c_int) -> bool {
487    TAINT_ENABLE.is_completed() && {
488        let reg_size = std::mem::size_of::<target_ptr_t>();
489
490        (0..reg_size).any(|offset| TAINT.taint2_query_reg(reg_num, offset as c_int) > 0)
491    }
492}
493
494/// Check if a specific byte of a register is tainted by any label, by the register number
495///
496/// ## Panics
497///
498/// This function panics if `byte_offset` is greater than or equal to the size of the register.
499///
500/// ### Notes
501///
502/// * When your given register is supported in the [`Reg`] API, use [`check_reg_byte`]
503/// * If taint has not been enabled by **your** plugin, this will return false
504pub fn check_reg_num_byte(reg_num: c_int, byte_offset: usize) -> bool {
505    assert!(byte_offset < std::mem::size_of::<target_ptr_t>());
506    TAINT_ENABLE.is_completed() && TAINT.taint2_query_reg(reg_num, byte_offset as c_int) > 0
507}
508
509/// Check if a byte in RAM is tainted by any label
510///
511/// ## Example
512///
513/// ```no_run
514/// use panda::taint;
515///
516/// if taint::check_ram(0xffff_0034) {
517///     println!("Variable at 0xffff_0034 is tainted")
518/// }
519/// ```
520///
521/// **Note:** If taint has not been enabled by **your** plugin, this will return false
522pub fn check_ram(addr: target_ptr_t) -> bool {
523    TAINT_ENABLE.is_completed() && TAINT.taint2_query_ram(addr as u64) > 0
524}
525
526/// Check if any of a range of bytes in RAM is tainted by any label
527///
528/// ## Example
529///
530/// ```no_run
531/// use panda::taint;
532///
533/// if taint::check_ram_range(0xffff_0034..0xffff_0038) {
534///     println!("Variable at 0xffff_0034 is tainted")
535/// }
536/// ```
537///
538/// **Note:** If taint has not been enabled by **your** plugin, this will return false
539pub fn check_ram_range(mut addr_range: Range<target_ptr_t>) -> bool {
540    TAINT_ENABLE.is_completed() && addr_range.any(|addr| TAINT.taint2_query_ram(addr as u64) > 0)
541}
542
543pub fn check_laddr(addr: u64, offset: u64) -> bool {
544    TAINT_ENABLE.is_completed() && TAINT.taint2_query_laddr(addr, offset) > 0
545}
546
547/// Get a list of all taint labels applied to a register, excluding duplicates across bytes
548pub fn get_reg(reg: impl Into<Reg>) -> Vec<u32> {
549    let labels: HashSet<u32> = iter_reg_labels(reg).collect();
550
551    labels.into_iter().collect()
552}
553
554/// Get a list of all taint labels applied to a specific byte of a register
555///
556/// ## Panics
557///
558/// This function panics if `byte_offset` is greater than or equal to the size of the register.
559pub fn get_reg_byte(reg: impl Into<Reg>, byte_offset: usize) -> Vec<u32> {
560    assert!(byte_offset < std::mem::size_of::<target_ptr_t>());
561    iter_reg_byte_labels(reg, byte_offset).collect()
562}
563
564/// Get a list of all taint labels applied to a byte of memory
565pub fn get_ram(addr: target_ptr_t) -> Vec<u32> {
566    let mut query_result = QueryResult::empty();
567    TAINT.taint2_query_ram_full(addr as u64, &mut query_result);
568
569    if check_ram(addr) {
570        LabelIter {
571            done: query_result.num_labels == 0,
572            query_result,
573        }
574        .collect()
575    } else {
576        Vec::with_capacity(0)
577    }
578}
579
580/// Get a unique list of all taint labels applied to a segment of memory
581pub fn get_ram_range(addr_range: Range<target_ptr_t>) -> Vec<u32> {
582    let labels: HashSet<u32> = iter_ram_labels(addr_range).collect();
583
584    labels.into_iter().collect()
585}
586
587/// Iterate over all the taint labels applied to a given register
588///
589/// **NOTE**: this will repeat labels if they are applied to multiple bytes in
590/// the register. For automatic deduplication behavior, try [`get_reg`].
591pub fn iter_reg_labels(reg: impl Into<Reg>) -> impl Iterator<Item = u32> {
592    let reg_size = std::mem::size_of::<target_ptr_t>();
593
594    let reg = reg.into();
595    (0..reg_size)
596        .map(move |i| iter_reg_byte_labels(reg, i))
597        .flatten()
598}
599
600/// Iterate over all the taint labels applied to a specific byte of a given register
601///
602/// ## Panics
603///
604/// This function panics if `byte_offset` is greater than or equal to the size of the register.
605pub fn iter_reg_byte_labels(reg: impl Into<Reg>, byte_offset: usize) -> impl Iterator<Item = u32> {
606    assert!(byte_offset < std::mem::size_of::<target_ptr_t>());
607
608    let reg = reg.into();
609
610    let mut query_result = QueryResult::empty();
611    TAINT.taint2_query_reg_full(reg as u32, byte_offset as u32, &mut query_result);
612
613    if TAINT.taint2_query_reg(reg as c_int, byte_offset as c_int) > 0 {
614        LabelIter {
615            done: query_result.is_empty_or_invalid(),
616            query_result,
617        }
618    } else {
619        LabelIter {
620            done: true,
621            query_result,
622        }
623    }
624}
625
626/// Iterate over all the taint labels applied to a segment of memory
627///
628/// **NOTE**: this will repeat labels if they are applied to multiple bytes in
629/// the memory range. For automatic deduplication behavior, try [`get_ram_range`].
630pub fn iter_ram_labels(addr_range: Range<target_ptr_t>) -> impl Iterator<Item = u32> {
631    addr_range
632        .map(move |addr| {
633            let mut query_result = QueryResult::empty();
634            TAINT.taint2_query_ram_full(addr as u64, &mut query_result);
635
636            if check_ram(addr) {
637                LabelIter {
638                    done: query_result.is_empty_or_invalid(),
639                    query_result,
640                }
641            } else {
642                LabelIter {
643                    done: true,
644                    query_result,
645                }
646            }
647        })
648        .flatten()
649}
650
651#[repr(C)]
652pub struct QueryResult {
653    num_labels: u32,
654    ls: *mut c_void,
655    it_end: *mut c_void,
656    it_curr: *mut c_void,
657    tcn: u32,
658    cb_mask: u8,
659}
660
661impl QueryResult {
662    fn empty() -> Self {
663        Self {
664            num_labels: 0,
665            ls: ptr::null_mut(),
666            it_end: ptr::null_mut(),
667            it_curr: ptr::null_mut(),
668            tcn: 0,
669            cb_mask: 0,
670        }
671    }
672
673    fn is_empty_or_invalid(&self) -> bool {
674        self.num_labels == 0 || self.it_end.is_null() || self.it_curr.is_null()
675    }
676}
677
678pub struct LabelIter {
679    query_result: QueryResult,
680    done: bool,
681}
682
683impl Iterator for LabelIter {
684    type Item = u32;
685
686    fn next(&mut self) -> Option<Self::Item> {
687        if self.done {
688            None
689        } else {
690            Some(TAINT.taint2_query_result_next(&mut self.query_result, &mut self.done))
691        }
692    }
693}
694
695// TODO: sym_enable, sym_label_ram, sym_label_reg