Skip to content

Commit

Permalink
fix(codecs): error when encoding maps whose lengths don't match entry…
Browse files Browse the repository at this point in the history
… count

Ref: #332
  • Loading branch information
rvagg authored and mvdan committed Jan 18, 2022
1 parent a16dd99 commit de5750b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
11 changes: 10 additions & 1 deletion codec/dagcbor/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc
func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options EncodeOptions) error {
// Emit start of map.
tk.Type = tok.TMapOpen
tk.Length = int(n.Length()) // TODO: overflow check
expectedLength := int(n.Length())
tk.Length = expectedLength // TODO: overflow check
if _, err := sink.Step(tk); err != nil {
return err
}
Expand All @@ -184,6 +185,9 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
}
entries = append(entries, entry{keyStr, v})
}
if len(entries) != expectedLength {
return fmt.Errorf("map Length() does not match number of MapIterator() entries")
}
// Apply the desired sort function.
switch options.MapSortMode {
case codec.MapSortMode_Lexical:
Expand Down Expand Up @@ -213,11 +217,13 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
}
} else { // no sorting
// Emit map contents (and recurse).
var entryCount int
for itr := n.MapIterator(); !itr.Done(); {
k, v, err := itr.Next()
if err != nil {
return err
}
entryCount++
tk.Type = tok.TString
tk.Str, err = k.AsString()
if err != nil {
Expand All @@ -230,6 +236,9 @@ func marshalMap(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options
return err
}
}
if entryCount != expectedLength {
return fmt.Errorf("map Length() does not match number of MapIterator() entries")
}
}
// Emit map close.
tk.Type = tok.TMapClose
Expand Down
11 changes: 10 additions & 1 deletion codec/dagjson/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
case datamodel.Kind_Map:
// Emit start of map.
tk.Type = tok.TMapOpen
tk.Length = int(n.Length()) // TODO: overflow check
expectedLength := int(n.Length())
tk.Length = expectedLength // TODO: overflow check
if _, err := sink.Step(&tk); err != nil {
return err
}
Expand All @@ -83,6 +84,9 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
}
entries = append(entries, entry{keyStr, v})
}
if len(entries) != expectedLength {
return fmt.Errorf("map Length() does not match number of MapIterator() entries")
}
// Apply the desired sort function.
switch options.MapSortMode {
case codec.MapSortMode_Lexical:
Expand All @@ -100,16 +104,21 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err
})
}
// Emit map contents (and recurse).
var entryCount int
for _, e := range entries {
tk.Type = tok.TString
tk.Str = e.key
entryCount++
if _, err := sink.Step(&tk); err != nil {
return err
}
if err := Marshal(e.value, sink, options); err != nil {
return err
}
}
if entryCount != expectedLength {
return fmt.Errorf("map Length() does not match number of MapIterator() entries")
}
} else {
// Don't sort map, emit map contents (and recurse).
for itr := n.MapIterator(); !itr.Done(); {
Expand Down

0 comments on commit de5750b

Please sign in to comment.