1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00

Prevent early_fmt code from triggering Go's allocator

When converting strings to []byte so that they can be used with the tty
io.Writer interface Go calls a runtime method called
"stringtoslicebyte". If the input length exceeds a particular size then
this method will allocate a new []byte and copy the data into it. This
obviously causes our kernel to crash.

To fix this, all early_fmt functions have been changed to iterate any
string arguments and output them to the active TTY one byte at a time.
This commit is contained in:
Achilleas Anagnostopoulos 2017-05-12 08:00:18 +01:00
parent d7028cee00
commit 6d3c463ee8

View File

@ -7,7 +7,7 @@ var (
errWrongArgType = []byte("%!(WRONGTYPE)") errWrongArgType = []byte("%!(WRONGTYPE)")
errNoVerb = []byte("%!(NOVERB)") errNoVerb = []byte("%!(NOVERB)")
errExtraArg = []byte("%!(EXTRA)") errExtraArg = []byte("%!(EXTRA)")
padding = []byte{' '} padding = byte(' ')
trueValue = []byte("true") trueValue = []byte("true")
falseValue = []byte("false") falseValue = []byte("false")
) )
@ -62,7 +62,9 @@ func Printf(format string, args ...interface{}) {
} }
if blockStart < blockEnd { if blockStart < blockEnd {
hal.ActiveTerminal.Write([]byte(format[blockStart:blockEnd])) for i := blockStart; i < blockEnd; i++ {
hal.ActiveTerminal.WriteByte(format[i])
}
} }
// Scan til we hit the format character // Scan til we hit the format character
@ -109,7 +111,9 @@ func Printf(format string, args ...interface{}) {
} }
if blockStart != blockEnd { if blockStart != blockEnd {
hal.ActiveTerminal.Write([]byte(format[blockStart:blockEnd])) for i := blockStart; i < blockEnd; i++ {
hal.ActiveTerminal.WriteByte(format[i])
}
} }
// Check for unused args // Check for unused args
@ -139,23 +143,25 @@ func fmtBool(v interface{}) {
// padding specified by padLen. This function uses hal.ActiveTerminal for its // padding specified by padLen. This function uses hal.ActiveTerminal for its
// output. // output.
func fmtString(v interface{}, padLen int) { func fmtString(v interface{}, padLen int) {
var sval []byte
switch castedVal := v.(type) { switch castedVal := v.(type) {
case string: case string:
sval = []byte(castedVal) fmtRepeat(padding, padLen-len(castedVal))
for i := 0; i < len(castedVal); i++ {
hal.ActiveTerminal.WriteByte(castedVal[i])
}
case []byte: case []byte:
sval = castedVal fmtRepeat(padding, padLen-len(castedVal))
hal.ActiveTerminal.Write(castedVal)
default: default:
hal.ActiveTerminal.Write(errWrongArgType) hal.ActiveTerminal.Write(errWrongArgType)
return
} }
}
for pad := padLen - len(sval); pad > 0; pad-- { // fmtRepeat writes count bytes with value ch to the hal.ActiveTerminal.
hal.ActiveTerminal.Write(padding) func fmtRepeat(ch byte, count int) {
for i := 0; i < count; i++ {
hal.ActiveTerminal.WriteByte(ch)
} }
hal.ActiveTerminal.Write(sval)
} }
// fmtInt prints out a formatted version of v in the requested base, applying the // fmtInt prints out a formatted version of v in the requested base, applying the