Coverage Report

Created: 2024-09-08 06:47

/src/draco/src/draco/metadata/metadata_decoder.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2017 The Draco Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
#include "draco/metadata/metadata_decoder.h"
16
17
#include <string>
18
19
#include "draco/core/varint_decoding.h"
20
21
namespace draco {
22
23
95
MetadataDecoder::MetadataDecoder() : buffer_(nullptr) {}
24
25
bool MetadataDecoder::DecodeMetadata(DecoderBuffer *in_buffer,
26
0
                                     Metadata *metadata) {
27
0
  if (!metadata) {
28
0
    return false;
29
0
  }
30
0
  buffer_ = in_buffer;
31
0
  return DecodeMetadata(metadata);
32
0
}
33
34
bool MetadataDecoder::DecodeGeometryMetadata(DecoderBuffer *in_buffer,
35
95
                                             GeometryMetadata *metadata) {
36
95
  if (!metadata) {
37
0
    return false;
38
0
  }
39
95
  buffer_ = in_buffer;
40
95
  uint32_t num_att_metadata = 0;
41
95
  if (!DecodeVarint(&num_att_metadata, buffer_)) {
42
0
    return false;
43
0
  }
44
  // Decode attribute metadata.
45
17.7k
  for (uint32_t i = 0; i < num_att_metadata; ++i) {
46
17.7k
    uint32_t att_unique_id;
47
17.7k
    if (!DecodeVarint(&att_unique_id, buffer_)) {
48
1
      return false;
49
1
    }
50
17.7k
    std::unique_ptr<AttributeMetadata> att_metadata =
51
17.7k
        std::unique_ptr<AttributeMetadata>(new AttributeMetadata());
52
17.7k
    att_metadata->set_att_unique_id(att_unique_id);
53
17.7k
    if (!DecodeMetadata(static_cast<Metadata *>(att_metadata.get()))) {
54
47
      return false;
55
47
    }
56
17.6k
    metadata->AddAttributeMetadata(std::move(att_metadata));
57
17.6k
  }
58
47
  return DecodeMetadata(static_cast<Metadata *>(metadata));
59
95
}
60
61
17.7k
bool MetadataDecoder::DecodeMetadata(Metadata *metadata) {
62
  // Limit metadata nesting depth to avoid stack overflow in destructor.
63
17.7k
  constexpr int kMaxSubmetadataLevel = 1000;
64
65
17.7k
  struct MetadataTuple {
66
17.7k
    Metadata *parent_metadata;
67
17.7k
    Metadata *decoded_metadata;
68
17.7k
    int level;
69
17.7k
  };
70
17.7k
  std::vector<MetadataTuple> metadata_stack;
71
17.7k
  metadata_stack.push_back({nullptr, metadata, 0});
72
59.1k
  while (!metadata_stack.empty()) {
73
41.4k
    const MetadataTuple mp = metadata_stack.back();
74
41.4k
    metadata_stack.pop_back();
75
41.4k
    metadata = mp.decoded_metadata;
76
77
41.4k
    if (mp.parent_metadata != nullptr) {
78
23.6k
      if (mp.level > kMaxSubmetadataLevel) {
79
1
        return false;
80
1
      }
81
23.6k
      std::string sub_metadata_name;
82
23.6k
      if (!DecodeName(&sub_metadata_name)) {
83
6
        return false;
84
6
      }
85
23.6k
      std::unique_ptr<Metadata> sub_metadata =
86
23.6k
          std::unique_ptr<Metadata>(new Metadata());
87
23.6k
      metadata = sub_metadata.get();
88
23.6k
      if (!mp.parent_metadata->AddSubMetadata(sub_metadata_name,
89
23.6k
                                              std::move(sub_metadata))) {
90
6
        return false;
91
6
      }
92
23.6k
    }
93
41.4k
    if (metadata == nullptr) {
94
0
      return false;
95
0
    }
96
97
41.4k
    uint32_t num_entries = 0;
98
41.4k
    if (!DecodeVarint(&num_entries, buffer_)) {
99
3
      return false;
100
3
    }
101
67.4k
    for (uint32_t i = 0; i < num_entries; ++i) {
102
26.0k
      if (!DecodeEntry(metadata)) {
103
47
        return false;
104
47
      }
105
26.0k
    }
106
41.3k
    uint32_t num_sub_metadata = 0;
107
41.3k
    if (!DecodeVarint(&num_sub_metadata, buffer_)) {
108
2
      return false;
109
2
    }
110
41.3k
    if (num_sub_metadata > buffer_->remaining_size()) {
111
      // The decoded number of metadata items is unreasonably high.
112
11
      return false;
113
11
    }
114
174k
    for (uint32_t i = 0; i < num_sub_metadata; ++i) {
115
133k
      metadata_stack.push_back(
116
133k
          {metadata, nullptr, mp.parent_metadata ? mp.level + 1 : mp.level});
117
133k
    }
118
41.3k
  }
119
17.6k
  return true;
120
17.7k
}
121
122
26.0k
bool MetadataDecoder::DecodeEntry(Metadata *metadata) {
123
26.0k
  std::string entry_name;
124
26.0k
  if (!DecodeName(&entry_name)) {
125
13
    return false;
126
13
  }
127
26.0k
  uint32_t data_size = 0;
128
26.0k
  if (!DecodeVarint(&data_size, buffer_)) {
129
7
    return false;
130
7
  }
131
26.0k
  if (data_size == 0) {
132
12
    return false;
133
12
  }
134
26.0k
  if (data_size > buffer_->remaining_size()) {
135
15
    return false;
136
15
  }
137
26.0k
  std::vector<uint8_t> entry_value(data_size);
138
26.0k
  if (!buffer_->Decode(&entry_value[0], data_size)) {
139
0
    return false;
140
0
  }
141
26.0k
  metadata->AddEntryBinary(entry_name, entry_value);
142
26.0k
  return true;
143
26.0k
}
144
145
49.7k
bool MetadataDecoder::DecodeName(std::string *name) {
146
49.7k
  uint8_t name_len = 0;
147
49.7k
  if (!buffer_->Decode(&name_len)) {
148
5
    return false;
149
5
  }
150
49.7k
  name->resize(name_len);
151
49.7k
  if (name_len == 0) {
152
9.08k
    return true;
153
9.08k
  }
154
40.6k
  if (!buffer_->Decode(&name->at(0), name_len)) {
155
14
    return false;
156
14
  }
157
40.6k
  return true;
158
40.6k
}
159
}  // namespace draco