Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KATC/IndexedDB] Handle padding after property name #1786

Merged
merged 3 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 34 additions & 14 deletions ee/indexeddb/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const (

// DeserializeChrome deserializes a JS object that has been stored by Chrome
// in IndexedDB LevelDB-backed databases.
func DeserializeChrome(_ context.Context, _ *slog.Logger, row map[string][]byte) (map[string][]byte, error) {
func DeserializeChrome(ctx context.Context, slogger *slog.Logger, row map[string][]byte) (map[string][]byte, error) {
data, ok := row["data"]
if !ok {
return nil, errors.New("row missing top-level data key")
Expand All @@ -57,7 +57,7 @@ func DeserializeChrome(_ context.Context, _ *slog.Logger, row map[string][]byte)
}

// Now, parse the actual data in this row
objData, err := deserializeObject(srcReader)
objData, err := deserializeObject(ctx, slogger, srcReader)
if err != nil {
return nil, fmt.Errorf("decoding obj for indexeddb version %d: %w", version, err)
}
Expand Down Expand Up @@ -96,7 +96,7 @@ func readHeader(srcReader io.ByteReader) (uint64, error) {
}

// deserializeObject deserializes the next object from the srcReader.
func deserializeObject(srcReader io.ByteReader) (map[string][]byte, error) {
func deserializeObject(ctx context.Context, slogger *slog.Logger, srcReader io.ByteReader) (map[string][]byte, error) {
obj := make(map[string][]byte)

for {
Expand Down Expand Up @@ -136,19 +136,16 @@ func deserializeObject(srcReader io.ByteReader) (map[string][]byte, error) {
currentPropertyName := string(objPropertyBytes)

// Now process the object property's value. The next byte will tell us its type.
nextByte, err := srcReader.ReadByte()
nextByte, err := nextNonPaddingByte(srcReader)
zackattack01 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
if err == io.EOF {
return obj, nil
}
return obj, fmt.Errorf("reading next byte: %w", err)
}

// Handle the object property value by its type.
switch nextByte {
case tokenObjectBegin:
// Object nested inside this object
nestedObj, err := deserializeNestedObject(srcReader)
nestedObj, err := deserializeNestedObject(ctx, slogger, srcReader)
if err != nil {
return obj, fmt.Errorf("decoding nested object for %s: %w", currentPropertyName, err)
}
Expand Down Expand Up @@ -181,22 +178,45 @@ func deserializeObject(srcReader io.ByteReader) (map[string][]byte, error) {
obj[currentPropertyName] = []byte(strconv.Itoa(int(propertyInt)))
case tokenBeginSparseArray:
// This is the only type of array I've encountered so far, so it's the only one implemented.
arr, err := deserializeSparseArray(srcReader)
arr, err := deserializeSparseArray(ctx, slogger, srcReader)
if err != nil {
return obj, fmt.Errorf("decoding array for %s: %w", currentPropertyName, err)
}
obj[currentPropertyName] = arr
case tokenPadding, tokenVerifyObjectCount:
fallthrough
// We don't care about these types
continue
default:
slogger.Log(ctx, slog.LevelWarn,
"unknown token type",
"token", fmt.Sprintf("%02x", nextByte),
)
continue
}
}
}

// nextNonPaddingByte reads from srcReader and discards `tokenPadding` until
// it reaches the next non-padded byte.
func nextNonPaddingByte(srcReader io.ByteReader) (byte, error) {
for {
nextByte, err := srcReader.ReadByte()
if err != nil {
if err == io.EOF {
return 0, fmt.Errorf("did not expect EOF reading next byte: %w", err)
}
return 0, fmt.Errorf("reading next byte: %w", err)
}
if nextByte == tokenPadding {
continue
}
return nextByte, nil
}
}

// deserializeSparseArray deserializes the next array from the srcReader.
// Currently, it only handles an array of objects.
func deserializeSparseArray(srcReader io.ByteReader) ([]byte, error) {
func deserializeSparseArray(ctx context.Context, slogger *slog.Logger, srcReader io.ByteReader) ([]byte, error) {
// After an array start, the next byte will be the length of the array.
arrayLen, err := binary.ReadUvarint(srcReader)
if err != nil {
Expand Down Expand Up @@ -252,7 +272,7 @@ func deserializeSparseArray(srcReader io.ByteReader) ([]byte, error) {
}
switch nextByte {
case tokenObjectBegin:
obj, err := deserializeNestedObject(srcReader)
obj, err := deserializeNestedObject(ctx, slogger, srcReader)
if err != nil {
return nil, fmt.Errorf("decoding object in array: %w", err)
}
Expand All @@ -270,8 +290,8 @@ func deserializeSparseArray(srcReader io.ByteReader) ([]byte, error) {
return arrBytes, nil
}

func deserializeNestedObject(srcReader io.ByteReader) ([]byte, error) {
nestedObj, err := deserializeObject(srcReader)
func deserializeNestedObject(ctx context.Context, slogger *slog.Logger, srcReader io.ByteReader) ([]byte, error) {
nestedObj, err := deserializeObject(ctx, slogger, srcReader)
if err != nil {
return nil, fmt.Errorf("deserializing nested object: %w", err)
}
Expand Down
9 changes: 9 additions & 0 deletions ee/katc/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ func (k *katcTable) generate(ctx context.Context, queryContext table.QueryContex
// Fetch data from our table source
dataRaw, err := k.sourceType.dataFunc(ctx, k.slogger, k.sourcePaths, k.sourceQuery, queryContext)
if err != nil {
k.slogger.Log(ctx, slog.LevelWarn,
"running data func",
"err", err,
)
return nil, fmt.Errorf("fetching data: %w", err)
}

Expand All @@ -127,6 +131,11 @@ func (k *katcTable) generate(ctx context.Context, queryContext table.QueryContex
for _, step := range k.rowTransformSteps {
dataRawRow, err = step.transformFunc(ctx, k.slogger, dataRawRow)
if err != nil {
k.slogger.Log(ctx, slog.LevelWarn,
"running transform func",
"transform_step", step.name,
"err", err,
)
return nil, fmt.Errorf("running transform func %s: %w", step.name, err)
}
}
Expand Down
Loading