fn gen_res(ctx: &mut ProgContext, ty: TypeRef, dir: Dir) -> Value {
    let special_value = || {
        let mut rng = thread_rng();
        ty.res_desc()
            .unwrap()
            .vals
            .iter()
            .copied()
            .choose(&mut rng)
            .unwrap_or_else(|| rng.gen())
    };
    let mut rng = thread_rng();
    if dir == Dir::Out || dir == Dir::InOut {
        ctx.call_ctx.res_cnt += 1;
        let mut res = Box::new(ResValue::new_res(0, ctx.next_id()));
        ctx.add_res(ty, &mut *res);
        Value::new(dir, ty, ValueKind::new_res(res))
    } else {
        // For most case, we reuse the generated resource even if the resource may not be the
        // precise one.
        if !ctx.res.is_empty() && rng.gen::<f32>() < 0.998 {
            // If we've already generated required resource, just reuse it.
            if let Some(generated_res) = ctx.res.get(&ty) {
                if !generated_res.is_empty() {
                    let res = generated_res.iter().choose(&mut rng).unwrap();
                    return Value::new(dir, ty, unsafe {
                        ValueKind::new_res_ref(res.as_mut().unwrap())
                    });
                }
            }
            // Otherwise, try to find the eq resource. Also handle unreachable resource here.
            let subtypes = &ctx.target.subtype_map[&ty];
            let supertypes = &ctx.target.supertype_map[&ty];
            let mut res_vals = Vec::new();

            for res in subtypes.iter().copied().chain(supertypes.iter().copied()) {
                if let Some(r) = ctx.res.get(&res) {
                    if !r.is_empty() {
                        res_vals.extend(r.iter().copied());
                    }
                }
            }
            if !res_vals.is_empty() {
                let res = res_vals.into_iter().choose(&mut rng).unwrap();
                return Value::new(dir, ty, unsafe {
                    ValueKind::new_res_ref(res.as_mut().unwrap())
                });
            }
            // We still haven't found any usable resource, try to choose a arbitrary generated
            // resource. May be we can use resource centric strategy here just like syzkaller.
            if let Some((_, vals)) = ctx.res.iter().choose(&mut rng) {
                if !vals.is_empty() && rng.gen_bool(0.9) {
                    let res = vals.iter().choose(&mut rng).unwrap();
                    return Value::new(dir, ty, unsafe {
                        ValueKind::new_res_ref(res.as_mut().unwrap())
                    });
                }
            }
        }

        let val = special_value();
        Value::new(dir, ty, ValueKind::new_res_null(val))
    }
}
/// Generate value for resource type.
Generate value for resource type.
Generate value for resource type .
fn gen_res(ctx: &mut ProgContext, ty: TypeRef, dir: Dir) -> Value {
    let special_value = || {
        let mut rng = thread_rng();
        ty.res_desc()
            .unwrap()
            .vals
            .iter()
            .copied()
            .choose(&mut rng)
            .unwrap_or_else(|| rng.gen())
    };
    let mut rng = thread_rng();
    if dir == Dir::Out || dir == Dir::InOut {
        ctx.call_ctx.res_cnt += 1;
        let mut res = Box::new(ResValue::new_res(0, ctx.next_id()));
        ctx.add_res(ty, &mut *res);
        Value::new(dir, ty, ValueKind::new_res(res))
    } else {
        // For most case, we reuse the generated resource even if the resource may not be the
        // precise one.
        if !ctx.res.is_empty() && rng.gen::<f32>() < 0.998 {
            // If we've already generated required resource, just reuse it.
            if let Some(generated_res) = ctx.res.get(&ty) {
                if !generated_res.is_empty() {
                    let res = generated_res.iter().choose(&mut rng).unwrap();
                    return Value::new(dir, ty, unsafe {
                        ValueKind::new_res_ref(res.as_mut().unwrap())
                    });
                }
            }
            // Otherwise, try to find the eq resource. Also handle unreachable resource here.
            let subtypes = &ctx.target.subtype_map[&ty];
            let supertypes = &ctx.target.supertype_map[&ty];
            let mut res_vals = Vec::new();
            for res in subtypes.iter().copied().chain(supertypes.iter().copied()) {
                if let Some(r) = ctx.res.get(&res) {
                    if !r.is_empty() {
                        res_vals.extend(r.iter().copied());
                    }
                }
            }
            if !res_vals.is_empty() {
                let res = res_vals.into_iter().choose(&mut rng).unwrap();
                return Value::new(dir, ty, unsafe {
                    ValueKind::new_res_ref(res.as_mut().unwrap())
                });
            }
            // We still haven't found any usable resource, try to choose a arbitrary generated
            // resource. May be we can use resource centric strategy here just like syzkaller.
            if let Some((_, vals)) = ctx.res.iter().choose(&mut rng) {
                if !vals.is_empty() && rng.gen_bool(0.9) {
                    let res = vals.iter().choose(&mut rng).unwrap();
                    return Value::new(dir, ty, unsafe {
                        ValueKind::new_res_ref(res.as_mut().unwrap())
                    });
                }
            }
        }
        let val = special_value();
        Value::new(dir, ty, ValueKind::new_res_null(val))
    }
}
fn gen_res ( ctx : & mut ProgContext , ty : TypeRef , dir : Dir ) -> Value { let special_value = | | { let mut rng = thread_rng ( ) ; ty . res_desc ( ) . unwrap ( ) . vals . iter ( ) . copied ( ) . choose ( & mut rng ) . unwrap_or_else ( | | rng . gen ( ) ) } ; let mut rng = thread_rng ( ) ; if dir == Dir :: Out || dir == Dir :: InOut { ctx . call_ctx . res_cnt += 1 ; let mut res = Box :: new ( ResValue :: new_res ( 0 , ctx . next_id ( ) ) ) ; ctx . add_res ( ty , & mut * res ) ; Value :: new ( dir , ty , ValueKind :: new_res ( res ) ) } else { // For most case, we reuse the generated resource even if the resource may not be the // precise one. if ! ctx . res . is_empty ( ) && rng . gen :: < f32 > ( ) < 0.998 { // If we've already generated required resource, just reuse it. if let Some ( generated_res ) = ctx . res . get ( & ty ) { if ! generated_res . is_empty ( ) { let res = generated_res . iter ( ) . choose ( & mut rng ) . unwrap ( ) ; return Value :: new ( dir , ty , unsafe { ValueKind :: new_res_ref ( res . as_mut ( ) . unwrap ( ) ) } ) ; } } // Otherwise, try to find the eq resource. Also handle unreachable resource here. let subtypes = & ctx . target . subtype_map [ & ty ] ; let supertypes = & ctx . target . supertype_map [ & ty ] ; let mut res_vals = Vec :: new ( ) ; for res in subtypes . iter ( ) . copied ( ) . chain ( supertypes . iter ( ) . copied ( ) ) { if let Some ( r ) = ctx . res . get ( & res ) { if ! r . is_empty ( ) { res_vals . extend ( r . iter ( ) . copied ( ) ) ; } } } if ! res_vals . is_empty ( ) { let res = res_vals . into_iter ( ) . choose ( & mut rng ) . unwrap ( ) ; return Value :: new ( dir , ty , unsafe { ValueKind :: new_res_ref ( res . as_mut ( ) . unwrap ( ) ) } ) ; } // We still haven't found any usable resource, try to choose a arbitrary generated // resource. May be we can use resource centric strategy here just like syzkaller. if let Some ( ( _ , vals ) ) = ctx . res . iter ( ) . choose ( & mut rng ) { if ! vals . is_empty ( ) && rng . gen_bool ( 0.9 ) { let res = vals . iter ( ) . choose ( & mut rng ) . unwrap ( ) ; return Value :: new ( dir , ty , unsafe { ValueKind :: new_res_ref ( res . as_mut ( ) . unwrap ( ) ) } ) ; } } } let val = special_value ( ) ; Value :: new ( dir , ty , ValueKind :: new_res_null ( val ) ) } }
Generate value for resource type.
Generate value for resource type .
ctx
&mut ProgContext
ty
TypeRef
dir
Dir
ctx
&mut ProgContext
ty
TypeRef
dir
Dir