From a1ce8e41033c69e6e32a465d5101177f7cd9cb50 Mon Sep 17 00:00:00 2001 From: Levin Alexander Date: Thu, 11 Oct 2018 13:01:02 +0000 Subject: [PATCH 1/2] Forward unhandled escape sequences unchanged Fixes parsing of HL7 Hex-Escape sequences (\X....\) and other variable-length escape sequences that are not handled by the parser code. This will break with an array overflow in case escape sequences are not paired correctly. --- messageparser.go | 7 +++++++ messageparser_test.go | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/messageparser.go b/messageparser.go index c757a70..1d7ae4a 100644 --- a/messageparser.go +++ b/messageparser.go @@ -225,6 +225,13 @@ func unescape(b []byte, d *Delimiters) []byte { r[j] = d.Escape j++ r[j] = c + j++ + i++ + for ; b[i] != d.Escape; i++ { + r[j] = b[i] + j++ + } + r[j] = d.Escape } j++ diff --git a/messageparser_test.go b/messageparser_test.go index ec3bdc3..c4157d9 100644 --- a/messageparser_test.go +++ b/messageparser_test.go @@ -287,7 +287,7 @@ func TestParseSimpleContent(t *testing.T) { Field{FieldItem{Component{"^~\\&"}}}, Field{FieldItem{Component{"field"}}}, Field{FieldItem{ - Component{"\\|~^&\\X484559"}, + Component{"\\|~^&\\X484559\\"}, }}, Field{FieldItem{ Component{"component1"}, @@ -321,6 +321,23 @@ func TestParseLiteralNewline(t *testing.T) { }, m) } +func TestParseTrailingHexEscapes(t *testing.T) { + a := assert.New(t) + + m, d, err := ParseMessage([]byte(`MSH|^~\&|Foo\X41\|Bar\X42\Fred`)) + a.NoError(err) + a.Equal(&Delimiters{'|', '^', '~', '\\', '&'}, d) + a.Equal(Message{ + Segment{ + Field{FieldItem{Component{`MSH`}}}, + Field{FieldItem{Component{`|`}}}, + Field{FieldItem{Component{`^~\&`}}}, + Field{FieldItem{Component{`Foo\X41\`}}}, + Field{FieldItem{Component{`Bar\X42\Fred`}}}, + }, + }, m) +} + func TestParseBad(t *testing.T) { a := assert.New(t) From 42a420207546ccda97498f4639f1c225a9f658c2 Mon Sep 17 00:00:00 2001 From: Levin Alexander Date: Thu, 11 Oct 2018 15:28:08 +0200 Subject: [PATCH 2/2] Silently fix unpaired escape characters in parsing --- messageparser.go | 4 ++-- messageparser_test.go | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/messageparser.go b/messageparser.go index 1d7ae4a..7073860 100644 --- a/messageparser.go +++ b/messageparser.go @@ -197,7 +197,7 @@ func ParseMessage(buf []byte) (Message, *Delimiters, error) { } func unescape(b []byte, d *Delimiters) []byte { - r := make([]byte, len(b)) + r := make([]byte, len(b)+1) // +1 to make room for possible unpaired escape character j, e := 0, false for i := 0; i < len(b); i++ { @@ -227,7 +227,7 @@ func unescape(b []byte, d *Delimiters) []byte { r[j] = c j++ i++ - for ; b[i] != d.Escape; i++ { + for ; i < len(b) && b[i] != d.Escape; i++ { r[j] = b[i] j++ } diff --git a/messageparser_test.go b/messageparser_test.go index c4157d9..7fd8992 100644 --- a/messageparser_test.go +++ b/messageparser_test.go @@ -321,7 +321,7 @@ func TestParseLiteralNewline(t *testing.T) { }, m) } -func TestParseTrailingHexEscapes(t *testing.T) { +func TestParseHexEscapes(t *testing.T) { a := assert.New(t) m, d, err := ParseMessage([]byte(`MSH|^~\&|Foo\X41\|Bar\X42\Fred`)) @@ -338,6 +338,23 @@ func TestParseTrailingHexEscapes(t *testing.T) { }, m) } +func TestParseUnpairedInvalidHexEscapes(t *testing.T) { + a := assert.New(t) + + m, d, err := ParseMessage([]byte(`MSH|^~\&|Foo\X41|Bar\X42\Fred`)) + a.NoError(err) + a.Equal(&Delimiters{'|', '^', '~', '\\', '&'}, d) + a.Equal(Message{ + Segment{ + Field{FieldItem{Component{`MSH`}}}, + Field{FieldItem{Component{`|`}}}, + Field{FieldItem{Component{`^~\&`}}}, + Field{FieldItem{Component{`Foo\X41\`}}}, + Field{FieldItem{Component{`Bar\X42\Fred`}}}, + }, + }, m) +} + func TestParseBad(t *testing.T) { a := assert.New(t)