Skip to content

Commit 18d248f

Browse files
committed
Meta: more correct handling of HTML-unescaping
It turns out that straight byte-based replacements of unicode escape characters back to their ascii representations is invalid if the unicode escape character itself is escaped (e.g. "\u003c" => "\\u003c" => "\<"). To solve this, we will instead unmarshal Meta objects to map[string]interface{}, extract the expected Meta fields from the map, and then use a JSON encoder with SetEscapeHTML(false) to re-encode the map back to JSON to be stored in Meta.Blob. Signed-off-by: Joe Lanford <[email protected]>
1 parent d482f98 commit 18d248f

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

alpha/declcfg/declcfg.go

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
77
"fmt"
88
"strings"
99

10-
"go4.org/bytereplacer"
11-
1210
"github.com/operator-framework/operator-registry/alpha/property"
1311
)
1412

@@ -100,25 +98,43 @@ func (m Meta) MarshalJSON() ([]byte, error) {
10098
}
10199

102100
func (m *Meta) UnmarshalJSON(blob []byte) error {
103-
blob = bytereplacer.New(`\u003c`, "<", `\u003e`, ">", `\u0026`, "&").Replace(blob)
101+
blobMap := map[string]interface{}{}
102+
if err := json.Unmarshal(blob, &blobMap); err != nil {
103+
return err
104+
}
105+
for key, ptr := range map[string]*string{"schema": &m.Schema, "package": &m.Package, "name": &m.Name} {
106+
if _, ok := blobMap[key]; !ok {
107+
continue
108+
}
109+
v, ok := blobMap[key].(string)
110+
if !ok {
111+
return fmt.Errorf("expected value for key %q to be a string, got %t: %v", key, blobMap[key], blobMap[key])
112+
}
113+
*ptr = v
114+
}
104115

105-
type tmp struct {
106-
Schema string `json:"schema"`
107-
Package string `json:"package,omitempty"`
108-
Name string `json:"name,omitempty"`
109-
Properties []property.Property `json:"properties,omitempty"`
116+
// TODO: this ensures we can continue parsing FBC templates whose FBC fields
117+
// begin with a capital letter. We should decide if we want to continue
118+
// supporting this or not. Then we either remove this comment or remove
119+
// this code (and the comment).
120+
for key, ptr := range map[string]*string{"Schema": &m.Schema, "Package": &m.Package, "Name": &m.Name} {
121+
if _, ok := blobMap[key]; !ok || *ptr != "" {
122+
continue
123+
}
124+
v, ok := blobMap[key].(string)
125+
if !ok {
126+
return fmt.Errorf("expected value for key %q to be a string, got %t: %v", key, blobMap[key], blobMap[key])
127+
}
128+
*ptr = v
110129
}
111-
var t tmp
112-
if err := json.Unmarshal(blob, &t); err != nil {
113-
// TODO: return an error that includes the the full JSON message,
114-
// the offset of the error, and the error message. Let callers
115-
// decide how to format it.
116-
return errors.New(resolveUnmarshalErr(blob, err))
130+
131+
buf := bytes.Buffer{}
132+
enc := json.NewEncoder(&buf)
133+
enc.SetEscapeHTML(false)
134+
if err := enc.Encode(blobMap); err != nil {
135+
return err
117136
}
118-
m.Schema = t.Schema
119-
m.Package = t.Package
120-
m.Name = t.Name
121-
m.Blob = blob
137+
m.Blob = buf.Bytes()
122138
return nil
123139
}
124140

alpha/template/composite/builder_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ func TestBasicBuilder(t *testing.T) {
5858
defer file.Close()
5959
fileData, err := io.ReadAll(file)
6060
require.NoError(t, err)
61-
fmt.Println(string(fileData))
6261
require.Equal(t, string(fileData), basicBuiltFbcYaml)
6362
},
6463
validateAssertions: func(t *testing.T, validateErr error) {
@@ -90,7 +89,6 @@ func TestBasicBuilder(t *testing.T) {
9089
defer file.Close()
9190
fileData, err := io.ReadAll(file)
9291
require.NoError(t, err)
93-
fmt.Println(string(fileData))
9492
require.Equal(t, string(fileData), basicBuiltFbcJson)
9593
},
9694
validateAssertions: func(t *testing.T, validateErr error) {

0 commit comments

Comments
 (0)