Memory Management
There are several important aspects to consider regarding memory management. Following the OWASP guidelines, the first step we must take to protect our application is the user input/output. Steps must be taken to ensure no malicious content is allowed. A more detailed overview of this aspect is in the Input Validation and the Output Encoding sections of this document.
Another important aspect regarding memory management is the buffer boundary
checking. When dealing with functions that accept a number of bytes to copy,
usually, in C-style languages, the size of the destination array must be checked
to ensure we don't write past the allocated space. In Go, data types such as
String
are not NULL terminated, and in the case of String
its header
consists of the following information:
type StringHeader struct {
Data uintptr
Len int
}
Despite this, boundary checks must be made (e.g. when looping).
If we go beyond the set boundaries, Go will Panic
.
A simple example:
func main() {
strings := []string{"aaa", "bbb", "ccc", "ddd"}
// Our loop is not checking the MAP length -> BAD
for i := 0; i < 5; i++ {
if len(strings[i]) > 0 {
fmt.Println(strings[i])
}
}
}
Output:
aaa
bbb
ccc
ddd
panic: runtime error: index out of range
When our application uses resources, additional checks must also be made to
ensure they have been closed and not rely solely on the Garbage Collector.
This is applicable when dealing with connection objects, file handles, etc.
In Go we can use Defer
to perform these actions. Instructions in Defer
are
only executed when the surrounding functions finish execution.
defer func() {
// Our cleanup code here
}
More information regarding Defer
can be found in the Error Handling
section of the document.
Usage of known vulnerable functions should also be avoided. In Go, the Unsafe
package contains these functions. They should not be used in production
environments, nor should the package itself. This also applies to the Testing
package.
On the other hand, memory deallocation is handled by the garbage collector, which means that we don't have to worry about it. An interesting note is that it is possible to manually deallocate memory although it is not advised.
Quoting Golang's Github:
If you really want to manually manage memory with Go, implement your own memory allocator based on syscall.Mmap or cgo malloc/free.
Disabling GC for extended period of time is generally a bad solution for a concurrent language like Go. And Go's GC will only be better down the road.