builtin: implement a double free detection for v strings

pull/5588/head
Delyan Angelov 2020-06-30 18:28:28 +03:00
parent f10d2bb75f
commit 2fd960f12c
2 changed files with 19 additions and 6 deletions

View File

@ -46,10 +46,18 @@ pub struct string {
pub: pub:
str byteptr // points to a C style 0 terminated string of bytes. str byteptr // points to a C style 0 terminated string of bytes.
len int // the length of the .str field, excluding the ending 0 byte. It is always equal to strlen(.str). len int // the length of the .str field, excluding the ending 0 byte. It is always equal to strlen(.str).
is_lit bool mut:
is_lit int
} }
// mut: // mut:
// hash_cache int // hash_cache int
//
// NB string.is_lit is an enumeration of the following:
// .is_lit == 0 => a fresh string, should be freed by autofree
// .is_lit == 1 => a literal string from .rodata, should NOT be freed
// .is_lit == -98761234 => already freed string, protects against double frees.
// ^^^^^^^^^ calling free on these is a bug.
// Any other value means that the string has been corrupted.
pub struct ustring { pub struct ustring {
pub mut: pub mut:
@ -109,7 +117,7 @@ pub fn tos_lit(s charptr) string {
return string{ return string{
str: byteptr(s) str: byteptr(s)
len: C.strlen(s) len: C.strlen(s)
is_lit:true is_lit: 1
} }
} }
@ -1186,10 +1194,15 @@ pub fn (c byte) is_letter() bool {
} }
pub fn (s &string) free() { pub fn (s &string) free() {
if s.is_lit || s.len == 0 { if s.is_lit == -98761234 {
C.printf('double string.free() detected\n')
return
}
if s.is_lit == 1 || s.len == 0 {
return return
} }
free(s.str) free(s.str)
s.is_lit = -98761234
} }
// all_before('23:34:45.234', '.') == '23:34:45' // all_before('23:34:45.234', '.') == '23:34:45'

View File

@ -108,7 +108,7 @@ string _STR_TMP(const char *fmt, ...) {
//puts(g_str_buf); //puts(g_str_buf);
#endif #endif
string res = tos(g_str_buf, len); string res = tos(g_str_buf, len);
res.is_lit = true; res.is_lit = 1;
return res; return res;
} // endof _STR_TMP } // endof _STR_TMP