Skip to content

Commit 9a1c978

Browse files
committed
common/io: Don't generate corrupted escape sequences in WriteData
1 parent 5f169ec commit 9a1c978

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed

common/io.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,13 @@ func min(a, b int) int {
136136
// Note: Error may occur even after some data is written so it's better
137137
// to just CAN transaction after WriteData error.
138138
func (p *Pipe) WriteData(input []byte) error {
139-
encoded := []byte(escapeParameters(string(input)))
140-
chunkLen := MaxLineLen - 3 // 3 is for 'D ' and line feed.
141-
for i := 0; i < len(encoded); i += chunkLen {
142-
chunk := encoded[i:min(i+chunkLen, len(encoded))]
143-
chunk = append([]byte{'D', ' '}, chunk...)
139+
// Encoding of all bytes increases stream size 3 times.
140+
// So by decreasing "chunk" size to 1/3 of it we
141+
// will never break this limit.
142+
chunkLen := MaxLineLen/3 - 3 // -3 is for 'D ' and line feed.
143+
for i := 0; i < len(input); i += chunkLen {
144+
chunk := input[i:min(i+chunkLen, len(input))]
145+
chunk = append([]byte{'D', ' '}, []byte(escapeParameters(string(chunk)))...)
144146
chunk = append(chunk, '\n')
145147

146148
if _, err := p.w.Write(chunk); err != nil {
@@ -153,7 +155,10 @@ func (p *Pipe) WriteData(input []byte) error {
153155
// WriteDataReader is similar to WriteData but sends data from input Reader
154156
// until EOF.
155157
func (p *Pipe) WriteDataReader(input io.Reader) error {
156-
chunkLen := MaxLineLen - 3 // 3 is for 'D ' and line feed.
158+
// Encoding of all bytes increases stream size 3 times.
159+
// So by decreasing "chunk" size to 1/3 of it we
160+
// will never break this limit.
161+
chunkLen := MaxLineLen/3 - 3 // -3 is for 'D ' and line feed.
157162
buf := make([]byte, chunkLen)
158163

159164
for {

common/io_test.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,26 @@ func TestPipe_WriteData(t *testing.T) {
124124
}
125125
}
126126
})
127+
t.Run("line wrapping + escaping", func(t *testing.T) {
128+
buf := bytes.Buffer{}
129+
pipe := common.NewPipe(nil, &buf)
130+
defer pipe.Close()
131+
132+
data := []byte(strings.Repeat("\n", common.MaxLineLen*7))
133+
134+
err := pipe.WriteData(data)
135+
136+
if err != nil {
137+
t.Error("Unexpected error on pipe.WriteData:", err)
138+
}
139+
splitten := strings.Split(buf.String(), "\n")
140+
for _, part := range splitten {
141+
if len(part)+1 > common.MaxLineLen {
142+
t.Error("pipe.WriteData wrote line bigger than MaxLineLen")
143+
t.FailNow()
144+
}
145+
}
146+
})
127147
t.Run("from io.Reader", func(t *testing.T) {
128148
buf := bytes.Buffer{}
129149
pipe := common.NewPipe(nil, &buf)
@@ -141,7 +161,27 @@ func TestPipe_WriteData(t *testing.T) {
141161
t.Errorf("pipe.WriteData wrote wrong line: '%s'", buf.String())
142162
}
143163
})
144-
// TODO: Test that wrapping is done correctly and no data is corrupted.
164+
t.Run("line wrapping + escaping (from io.Reader)", func(t *testing.T) {
165+
buf := bytes.Buffer{}
166+
pipe := common.NewPipe(nil, &buf)
167+
defer pipe.Close()
168+
169+
data := []byte(strings.Repeat("\n", common.MaxLineLen*7))
170+
171+
err := pipe.WriteDataReader(bytes.NewReader(data))
172+
173+
if err != nil {
174+
t.Error("Unexpected error on pipe.WriteData:", err)
175+
t.FailNow()
176+
}
177+
splitten := strings.Split(buf.String(), "\n")
178+
for _, part := range splitten {
179+
if len(part)+1 > common.MaxLineLen {
180+
t.Error("pipe.WriteData wrote line bigger than MaxLineLen")
181+
t.FailNow()
182+
}
183+
}
184+
})
145185
}
146186

147187
func TestPipe_ReadData(t *testing.T) {

0 commit comments

Comments
 (0)