Skip to content

Commit

Permalink
Fix truncated entity error for ampersand literal
Browse files Browse the repository at this point in the history
  • Loading branch information
godexsoft committed Jul 25, 2019
1 parent 0e68bea commit ed86b2f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 43 deletions.
96 changes: 53 additions & 43 deletions internal/shared/parseutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,60 +96,70 @@ func DecodeEntities(str string) (string, error) {
break
}

// Write and skip everything before it
buf.Write(data[:idx])
data = data[idx+1:]
data = data[idx:]

if len(data) == 0 {
return "", TruncatedEntity
// If there is only the '&' left here
if len(data) == 1 {
buf.Write(data)
return buf.String(), nil
}

// Find the end of the entity
end := bytes.IndexByte(data, ';')
if end == -1 {
return "", TruncatedEntity
// it's not an entitiy. just a plain old '&' possibly with extra bytes
buf.Write(data)
return buf.String(), nil
}

if data[0] == '#' {
// Numerical character reference
var str string
base := 10

if len(data) > 1 && data[1] == 'x' {
str = string(data[2:end])
base = 16
} else {
str = string(data[1:end])
}

i, err := strconv.ParseUint(str, base, 32)
if err != nil {
return "", InvalidNumericReference
}

buf.WriteRune(rune(i))
// Check if there is a space somewhere within the 'entitiy'.
// If there is then skip the whole thing since it's not a real entity.
if strings.Contains(string(data[1:end]), " ") {
buf.Write(data)
return buf.String(), nil
} else {
// Predefined entity
name := string(data[:end])

var c byte
switch name {
case "lt":
c = '<'
case "gt":
c = '>'
case "quot":
c = '"'
case "apos":
c = '\''
case "amp":
c = '&'
default:
return "", fmt.Errorf("unknown predefined "+
"entity &%s;", name)
if data[1] == '#' {
// Numerical character reference
var str string
base := 10

if len(data) > 2 && data[2] == 'x' {
str = string(data[3:end])
base = 16
} else {
str = string(data[2:end])
}

i, err := strconv.ParseUint(str, base, 32)
if err != nil {
return "", InvalidNumericReference
}

buf.WriteRune(rune(i))
} else {
// Predefined entity
name := string(data[1:end])

var c byte
switch name {
case "lt":
c = '<'
case "gt":
c = '>'
case "quot":
c = '"'
case "apos":
c = '\''
case "amp":
c = '&'
default:
return "", fmt.Errorf("unknown predefined "+
"entity &%s;", name)
}

buf.WriteByte(c)
}

buf.WriteByte(c)
}

// Skip the entity
Expand Down
2 changes: 2 additions & 0 deletions internal/shared/parseutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ func TestDecodeEntities(t *testing.T) {
}{
{"", ""},
{"foo", "foo"},
{"skip & normal & amps", "skip & normal & amps"},
{"not & entity;hello &ne xt;one", "not & entity;hello &ne xt;one"},

{"&lt;foo&gt;", "<foo>"},
{"a &quot;b&quot; &apos;c&apos;", "a \"b\" 'c'"},
Expand Down

0 comments on commit ed86b2f

Please sign in to comment.