Fix #4890
`strings.to_cstring` previously would not check if the buffer could handle the extra null byte and could lead to segmentation violations when using the resulting string in an API expecting the terminator.
This commit is contained in:
5 files changed
+39
-16
No files matched your search
@@ -46,7 +46,7 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err
|
|||||||
strings.write_string(&buf, "/")
|
strings.write_string(&buf, "/")
|
||||||
strings.write_string(&buf, sarg)
|
strings.write_string(&buf, sarg)
|
||||||
|
|
||||||
cpath := strings.to_cstring(&buf)
|
cpath := strings.to_cstring(&buf) or_return
|
||||||
if posix.access(cpath, {.X_OK}) == .OK {
|
if posix.access(cpath, {.X_OK}) == .OK {
|
||||||
return real(cpath, allocator)
|
return real(cpath, allocator)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
|||||||
strings.write_string(&rname, "/dev/fd/")
|
strings.write_string(&rname, "/dev/fd/")
|
||||||
strings.write_int(&rname, int(fds[0]))
|
strings.write_int(&rname, int(fds[0]))
|
||||||
ri.name = strings.to_string(rname)
|
ri.name = strings.to_string(rname)
|
||||||
ri.cname = strings.to_cstring(&rname)
|
ri.cname = strings.to_cstring(&rname) or_return
|
||||||
|
|
||||||
w = __new_file(fds[1], file_allocator())
|
w = __new_file(fds[1], file_allocator())
|
||||||
wi := (^File_Impl)(w.impl)
|
wi := (^File_Impl)(w.impl)
|
||||||
@@ -39,7 +39,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
|
|||||||
strings.write_string(&wname, "/dev/fd/")
|
strings.write_string(&wname, "/dev/fd/")
|
||||||
strings.write_int(&wname, int(fds[1]))
|
strings.write_int(&wname, int(fds[1]))
|
||||||
wi.name = strings.to_string(wname)
|
wi.name = strings.to_string(wname)
|
||||||
wi.cname = strings.to_cstring(&wname)
|
wi.cname = strings.to_cstring(&wname) or_return
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
|||||||
|
|
||||||
strings.write_string(&path_builder, "/proc/")
|
strings.write_string(&path_builder, "/proc/")
|
||||||
strings.write_int(&path_builder, pid)
|
strings.write_int(&path_builder, pid)
|
||||||
proc_fd, errno := linux.open(strings.to_cstring(&path_builder), _OPENDIR_FLAGS)
|
proc_fd, errno := linux.open(strings.to_cstring(&path_builder) or_return, _OPENDIR_FLAGS)
|
||||||
if errno != .NONE {
|
if errno != .NONE {
|
||||||
err = _get_platform_error(errno)
|
err = _get_platform_error(errno)
|
||||||
return
|
return
|
||||||
@@ -169,7 +169,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
|||||||
strings.write_int(&path_builder, pid)
|
strings.write_int(&path_builder, pid)
|
||||||
strings.write_string(&path_builder, "/cmdline")
|
strings.write_string(&path_builder, "/cmdline")
|
||||||
|
|
||||||
cmdline_bytes, cmdline_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator())
|
cmdline_bytes, cmdline_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator())
|
||||||
if cmdline_err != nil || len(cmdline_bytes) == 0 {
|
if cmdline_err != nil || len(cmdline_bytes) == 0 {
|
||||||
err = cmdline_err
|
err = cmdline_err
|
||||||
break cmdline_if
|
break cmdline_if
|
||||||
@@ -190,7 +190,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
|||||||
strings.write_int(&path_builder, pid)
|
strings.write_int(&path_builder, pid)
|
||||||
strings.write_string(&path_builder, "/cwd")
|
strings.write_string(&path_builder, "/cwd")
|
||||||
|
|
||||||
cwd, cwd_err = _read_link_cstr(strings.to_cstring(&path_builder), temp_allocator()) // allowed to fail
|
cwd, cwd_err = _read_link_cstr(strings.to_cstring(&path_builder) or_return, temp_allocator()) // allowed to fail
|
||||||
if cwd_err == nil && .Working_Dir in selection {
|
if cwd_err == nil && .Working_Dir in selection {
|
||||||
info.working_dir = strings.clone(cwd, allocator) or_return
|
info.working_dir = strings.clone(cwd, allocator) or_return
|
||||||
info.fields += {.Working_Dir}
|
info.fields += {.Working_Dir}
|
||||||
@@ -258,7 +258,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
|||||||
strings.write_int(&path_builder, pid)
|
strings.write_int(&path_builder, pid)
|
||||||
strings.write_string(&path_builder, "/stat")
|
strings.write_string(&path_builder, "/stat")
|
||||||
|
|
||||||
proc_stat_bytes, stat_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator())
|
proc_stat_bytes, stat_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator())
|
||||||
if stat_err != nil {
|
if stat_err != nil {
|
||||||
err = stat_err
|
err = stat_err
|
||||||
break stat_if
|
break stat_if
|
||||||
@@ -330,7 +330,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
|
|||||||
strings.write_int(&path_builder, pid)
|
strings.write_int(&path_builder, pid)
|
||||||
strings.write_string(&path_builder, "/environ")
|
strings.write_string(&path_builder, "/environ")
|
||||||
|
|
||||||
if env_bytes, env_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator()); env_err == nil {
|
if env_bytes, env_err := _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator()); env_err == nil {
|
||||||
env := string(env_bytes)
|
env := string(env_bytes)
|
||||||
|
|
||||||
env_list := make([dynamic]string, allocator) or_return
|
env_list := make([dynamic]string, allocator) or_return
|
||||||
@@ -418,7 +418,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
strings.write_byte(&exe_builder, '/')
|
strings.write_byte(&exe_builder, '/')
|
||||||
strings.write_string(&exe_builder, executable_name)
|
strings.write_string(&exe_builder, executable_name)
|
||||||
|
|
||||||
exe_path = strings.to_cstring(&exe_builder)
|
exe_path = strings.to_cstring(&exe_builder) or_return
|
||||||
if linux.access(exe_path, linux.X_OK) == .NONE {
|
if linux.access(exe_path, linux.X_OK) == .NONE {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
@@ -430,7 +430,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
strings.write_string(&exe_builder, "./")
|
strings.write_string(&exe_builder, "./")
|
||||||
strings.write_string(&exe_builder, executable_name)
|
strings.write_string(&exe_builder, executable_name)
|
||||||
|
|
||||||
exe_path = strings.to_cstring(&exe_builder)
|
exe_path = strings.to_cstring(&exe_builder) or_return
|
||||||
if linux.access(exe_path, linux.X_OK) != .NONE {
|
if linux.access(exe_path, linux.X_OK) != .NONE {
|
||||||
return process, .Not_Exist
|
return process, .Not_Exist
|
||||||
}
|
}
|
||||||
@@ -594,7 +594,7 @@ _process_state_update_times :: proc(state: ^Process_State) -> (err: Error) {
|
|||||||
strings.write_string(&path_builder, "/stat")
|
strings.write_string(&path_builder, "/stat")
|
||||||
|
|
||||||
stat_buf: []u8
|
stat_buf: []u8
|
||||||
stat_buf, err = _read_entire_pseudo_file(strings.to_cstring(&path_builder), temp_allocator())
|
stat_buf, err = _read_entire_pseudo_file(strings.to_cstring(&path_builder) or_return, temp_allocator())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
strings.write_byte(&exe_builder, '/')
|
strings.write_byte(&exe_builder, '/')
|
||||||
strings.write_string(&exe_builder, exe_name)
|
strings.write_string(&exe_builder, exe_name)
|
||||||
|
|
||||||
if exe_fd := posix.open(strings.to_cstring(&exe_builder), {.CLOEXEC, .EXEC}); exe_fd == -1 {
|
if exe_fd := posix.open(strings.to_cstring(&exe_builder) or_return, {.CLOEXEC, .EXEC}); exe_fd == -1 {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
posix.close(exe_fd)
|
posix.close(exe_fd)
|
||||||
@@ -91,7 +91,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
|
|
||||||
// "hello/./world" is fine right?
|
// "hello/./world" is fine right?
|
||||||
|
|
||||||
if exe_fd := posix.open(strings.to_cstring(&exe_builder), {.CLOEXEC, .EXEC}); exe_fd == -1 {
|
if exe_fd := posix.open(strings.to_cstring(&exe_builder) or_return, {.CLOEXEC, .EXEC}); exe_fd == -1 {
|
||||||
err = .Not_Exist
|
err = .Not_Exist
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -102,7 +102,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
strings.builder_reset(&exe_builder)
|
strings.builder_reset(&exe_builder)
|
||||||
strings.write_string(&exe_builder, exe_name)
|
strings.write_string(&exe_builder, exe_name)
|
||||||
|
|
||||||
if exe_fd := posix.open(strings.to_cstring(&exe_builder), {.CLOEXEC, .EXEC}); exe_fd == -1 {
|
if exe_fd := posix.open(strings.to_cstring(&exe_builder) or_return, {.CLOEXEC, .EXEC}); exe_fd == -1 {
|
||||||
err = .Not_Exist
|
err = .Not_Exist
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -181,7 +181,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
if posix.chdir(cwd) != .OK { abort(pipe[WRITE]) }
|
if posix.chdir(cwd) != .OK { abort(pipe[WRITE]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
res := posix.execve(strings.to_cstring(&exe_builder), raw_data(cmd), env)
|
res := posix.execve(strings.to_cstring(&exe_builder) or_return, raw_data(cmd), env)
|
||||||
assert(res == -1)
|
assert(res == -1)
|
||||||
abort(pipe[WRITE])
|
abort(pipe[WRITE])
|
||||||
|
|
||||||
|
|||||||
@@ -288,18 +288,41 @@ to_string :: proc(b: Builder) -> (res: string) {
|
|||||||
/*
|
/*
|
||||||
Appends a trailing null byte after the end of the current Builder byte buffer and then casts it to a cstring
|
Appends a trailing null byte after the end of the current Builder byte buffer and then casts it to a cstring
|
||||||
|
|
||||||
|
NOTE: This procedure will not check if the backing buffer has enough space to include the extra null byte.
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
- b: A pointer to builder
|
- b: A pointer to builder
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
- res: A cstring of the Builder's buffer
|
- res: A cstring of the Builder's buffer
|
||||||
*/
|
*/
|
||||||
to_cstring :: proc(b: ^Builder) -> (res: cstring) {
|
unsafe_to_cstring :: proc(b: ^Builder) -> (res: cstring) {
|
||||||
append(&b.buf, 0)
|
append(&b.buf, 0)
|
||||||
pop(&b.buf)
|
pop(&b.buf)
|
||||||
return cstring(raw_data(b.buf))
|
return cstring(raw_data(b.buf))
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
Appends a trailing null byte after the end of the current Builder byte buffer and then casts it to a cstring
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- b: A pointer to builder
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- res: A cstring of the Builder's buffer upon success
|
||||||
|
- err: An optional allocator error if one occured, `nil` otherwise
|
||||||
|
*/
|
||||||
|
to_cstring :: proc(b: ^Builder) -> (res: cstring, err: mem.Allocator_Error) {
|
||||||
|
n := append(&b.buf, 0) or_return
|
||||||
|
if n != 1 {
|
||||||
|
return nil, .Out_Of_Memory
|
||||||
|
}
|
||||||
|
pop(&b.buf)
|
||||||
|
#no_bounds_check {
|
||||||
|
assert(b.buf[len(b.buf)] == 0)
|
||||||
|
}
|
||||||
|
return cstring(raw_data(b.buf)), nil
|
||||||
|
}
|
||||||
|
/*
|
||||||
Returns the length of the Builder's buffer, in bytes
|
Returns the length of the Builder's buffer, in bytes
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
|
|||||||
Reference in new issue
Block a user