email: bound the MIME walk and drop two copies of every body (V-581)
The MIME tree walk had no depth limit, and the nesting comes off the wire. A boundary line is a few bytes, so one message inside MaxMessageBytes can declare tens of thousands of multipart levels and pick the recursion depth of a daemon reading his mail. MaxMIMEDepth stops the walk at 12, well past the three levels real mail uses, and the headers still come through. ParseMessage converted the raw message to a string to read it, which copied up to 2 MiB per mail on a box already holding the resident model. It reads the bytes directly now. decodeCP1251 collected runes and then copied them into a string, four bytes a character for the whole body, and writes into a Builder instead. No behaviour change to what is read: EXAMINE and BODY.PEEK are still the only mailbox commands, and no credential reaches a log line. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package email
|
||||
|
||||
import "strings"
|
||||
|
||||
// windows-1251 (and its ASCII-compatible low half) is decoded here rather than
|
||||
// pulled in from x/text.
|
||||
//
|
||||
@@ -35,14 +37,19 @@ var cp1251High = [128]rune{
|
||||
|
||||
// decodeCP1251 maps each byte through the table. Every byte has a defined
|
||||
// meaning in this charset, so decoding cannot fail.
|
||||
//
|
||||
// It writes into a Builder rather than collecting runes: a []rune of the whole
|
||||
// body is four bytes a character and was then copied again into the string, so
|
||||
// a 1 MiB cp1251 mail allocated about 6 MiB to produce roughly 2.
|
||||
func decodeCP1251(b []byte) string {
|
||||
out := make([]rune, 0, len(b))
|
||||
var out strings.Builder
|
||||
out.Grow(len(b))
|
||||
for _, c := range b {
|
||||
if c < 0x80 {
|
||||
out = append(out, rune(c))
|
||||
out.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
out = append(out, cp1251High[c-0x80])
|
||||
out.WriteRune(cp1251High[c-0x80])
|
||||
}
|
||||
return string(out)
|
||||
return out.String()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user