Memory unsafety in `sub_self_call`
I caught this while working on #38 (closed). The code for sub_self_call
looks something like this (simplified):
// Get pointers to the varname and to the first subscript
let (varname, subscripts) = self.get_buffers();
// 1
let t = self.subscripts.last_mut().unwrap_or(unsafe { self.variable.as_mut_vec() });
loop {
// pretend this is initialized to zeros, doesn't matter for this example
let last_self_buffer: ydb_buffer_t = todo!();
let status = unsafe {
ydb_subscript_next_st(
tptoken.0,
&mut err_buffer_t,
varname.as_ptr(), // 3
subscripts.len() as i32,
subscripts.as_ptr() as *const _,
&mut last_self_buffer,
)
};
if status == YDB_ERR_INVSTRLEN {
t.reserve(last_self_buffer.len_used); // 2
continue;
}
}
This is broken: if t
is self.variable
(1), then t.reserve
can reallocate it (2), at which point varname.as_ptr()
points to freed memory (3).
I don't yet have a test showing a double-free due to this, but I'm sure it's possible.