| 190 | } // namespace |
| 191 | |
| 192 | std::string FormatStatValue(Type::type parquet_type, ::std::string_view val, |
| 193 | const std::shared_ptr<const LogicalType>& logical_type) { |
| 194 | // Statistics values come straight from the file's Thrift metadata, so their |
| 195 | // length is attacker controlled and the spec allows them to be truncated. |
| 196 | // Every fixed-width read below clamps its copy to val.size() so a too-short |
| 197 | // value cannot drive a load past the end of the buffer. |
| 198 | std::stringstream result; |
| 199 | const char* bytes = val.data(); |
| 200 | switch (parquet_type) { |
| 201 | case Type::BOOLEAN: { |
| 202 | bool value{}; |
| 203 | std::memcpy(&value, bytes, std::min(sizeof(bool), val.size())); |
| 204 | result << value; |
| 205 | break; |
| 206 | } |
| 207 | case Type::INT32: { |
| 208 | if (logical_type != nullptr && logical_type->is_decimal()) { |
| 209 | return FormatDecimalValue(parquet_type, val, logical_type); |
| 210 | } |
| 211 | return FormatNumericValue<int32_t>(val); |
| 212 | } |
| 213 | case Type::INT64: { |
| 214 | if (logical_type != nullptr && logical_type->is_decimal()) { |
| 215 | return FormatDecimalValue(parquet_type, val, logical_type); |
| 216 | } |
| 217 | return FormatNumericValue<int64_t>(val); |
| 218 | } |
| 219 | case Type::DOUBLE: { |
| 220 | return FormatNumericValue<double>(val); |
| 221 | } |
| 222 | case Type::FLOAT: { |
| 223 | return FormatNumericValue<float>(val); |
| 224 | } |
| 225 | case Type::INT96: { |
| 226 | std::array<int32_t, 3> values{}; |
| 227 | std::memcpy(values.data(), bytes, std::min(sizeof(values), val.size())); |
| 228 | result << values[0] << " " << values[1] << " " << values[2]; |
| 229 | break; |
| 230 | } |
| 231 | case Type::BYTE_ARRAY: |
| 232 | case Type::FIXED_LEN_BYTE_ARRAY: { |
| 233 | if (logical_type != nullptr) { |
| 234 | if (logical_type->is_decimal()) { |
| 235 | return FormatDecimalValue(parquet_type, val, logical_type); |
| 236 | } |
| 237 | if (logical_type->is_string()) { |
| 238 | return std::string(val); |
| 239 | } |
| 240 | if (logical_type->is_float16()) { |
| 241 | return FormatFloat16Value(val); |
| 242 | } |
| 243 | } |
| 244 | return FormatNonUTF8Value(val); |
| 245 | } |
| 246 | case Type::UNDEFINED: |
| 247 | default: |
| 248 | break; |
| 249 | } |