Skip to content

Commit 0cc8670

Browse files
committed
Fix strings example
Two problems were fixed: - the terminating null byte of strings was being encoded as well, which changed the size of the char array (and changed the underlying LLVM type, leading to a crash) - non-utf8 strings were being encoded as well, which raised integer overflow errors when encoding them
1 parent 57b018a commit 0cc8670

File tree

1 file changed

+38
-41
lines changed

1 file changed

+38
-41
lines changed

examples/strings.rs

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -53,55 +53,52 @@ enum GlobalString<'a> {
5353
}
5454

5555
fn encode_global_strings<'a>(module: &mut Module<'a>) -> Vec<GlobalString<'a>> {
56-
let mut global_strings = Vec::new();
5756
let cx = module.get_context();
5857

59-
for global in module.get_globals() {
60-
// ignore external globals
61-
if matches!(global.get_linkage(), Linkage::External) {
62-
continue;
63-
}
64-
65-
match global.get_initializer() {
58+
module
59+
.get_globals()
60+
.filter(|global| !matches!(global.get_linkage(), Linkage::External))
61+
.filter_map(|global| match global.get_initializer()? {
6662
// C-like strings
67-
Some(BasicValueEnum::ArrayValue(arr)) if arr.is_const_string() => {
68-
let encoded_str = match arr.get_string_constant() {
69-
Some(s) => s
70-
.to_bytes_with_nul()
71-
.iter()
72-
.map(|c| *c + 1)
73-
.collect::<Vec<_>>(),
74-
None => continue,
75-
};
76-
let new_const = cx.const_string(&encoded_str, false);
77-
global.set_initializer(&new_const);
78-
global.set_constant(false);
79-
global_strings.push(GlobalString::Array(global, encoded_str.len() as u32));
80-
}
63+
BasicValueEnum::ArrayValue(arr) => Some((global, None, arr)),
8164
// Rust-like strings
82-
Some(BasicValueEnum::StructValue(stru)) if stru.count_fields() <= 1 => {
83-
let arr = match stru.get_field_at_index(0) {
84-
Some(BasicValueEnum::ArrayValue(arr)) if arr.is_const_string() => arr,
85-
_ => continue,
86-
};
87-
let encoded_str = match arr.get_string_constant() {
88-
Some(s) => s
89-
.to_bytes_with_nul()
90-
.iter()
91-
.map(|c| *c + 1)
92-
.collect::<Vec<_>>(),
93-
None => continue,
94-
};
65+
BasicValueEnum::StructValue(stru) if stru.count_fields() <= 1 => {
66+
match stru.get_field_at_index(0)? {
67+
BasicValueEnum::ArrayValue(arr) => Some((global, Some(stru), arr)),
68+
_ => None,
69+
}
70+
}
71+
_ => None,
72+
})
73+
.filter(|(_, _, arr)| {
74+
// needs to be called before `get_string_constant`, otherwise it may crash
75+
arr.is_const_string()
76+
})
77+
.filter_map(|(global, stru, arr)| {
78+
// we ignore non-UTF8 strings, since they are probably not human-readable
79+
let s = arr.get_string_constant().and_then(|s| s.to_str().ok())?;
80+
let encoded_str = s.bytes().map(|c| c + 1).collect::<Vec<_>>();
81+
Some((global, stru, encoded_str))
82+
})
83+
.map(|(global, stru, encoded_str)| {
84+
if let Some(stru) = stru {
85+
// Rust-like strings
9586
let new_const = cx.const_string(&encoded_str, false);
9687
stru.set_field_at_index(0, new_const);
88+
global.set_initializer(&stru);
9789
global.set_constant(false);
98-
global_strings.push(GlobalString::Struct(global, 0, encoded_str.len() as u32));
99-
}
100-
_ => (),
101-
}
102-
}
10390

104-
global_strings
91+
GlobalString::Struct(global, 0, encoded_str.len() as u32)
92+
} else {
93+
// C-like strings
94+
let new_const = cx.const_string(&encoded_str, false);
95+
global.set_initializer(&new_const);
96+
global.set_constant(false);
97+
98+
GlobalString::Array(global, encoded_str.len() as u32)
99+
}
100+
})
101+
.collect()
105102
}
106103

107104
fn create_decode_fn<'a>(module: &mut Module<'a>) -> FunctionValue<'a> {

0 commit comments

Comments
 (0)