|
24 | 24 | #include "Utility.h" |
25 | 25 | #include "extended/ResourceLoaderExtended.h" |
26 | 26 |
|
| 27 | +#include <limits> |
27 | 28 | #include <filament/BufferObject.h> |
28 | 29 | #include <filament/Engine.h> |
29 | 30 | #include <filament/IndexBuffer.h> |
@@ -163,9 +164,40 @@ inline void normalizeSkinningWeights(cgltf_data const* gltf) { |
163 | 164 | LOG(WARNING) << "Cannot normalize weights, unsupported attribute type."; |
164 | 165 | return; |
165 | 166 | } |
| 167 | + if (!data->buffer_view || !data->buffer_view->buffer || |
| 168 | + !data->buffer_view->buffer->data) { |
| 169 | + LOG(WARNING) << "Cannot normalize weights, missing buffer data."; |
| 170 | + return; |
| 171 | + } |
| 172 | + const cgltf_size bufferSize = data->buffer_view->buffer->size; |
| 173 | + const cgltf_size viewOffset = data->buffer_view->offset; |
| 174 | + const cgltf_size accessorOffset = data->offset; |
| 175 | + const cgltf_size totalOffset = viewOffset + accessorOffset; |
| 176 | + |
| 177 | + if (totalOffset >= bufferSize) { |
| 178 | + LOG(WARNING) << "Cannot normalize weights, accessor offset exceeds buffer size."; |
| 179 | + return; |
| 180 | + } |
| 181 | + |
| 182 | + const cgltf_size availableBytes = bufferSize - totalOffset; |
| 183 | + const cgltf_size stride = data->stride; |
| 184 | + |
| 185 | + cgltf_size maxCount = 0; |
| 186 | + if (stride > 0 && availableBytes >= sizeof(float4)) { |
| 187 | + maxCount = 1 + (availableBytes - sizeof(float4)) / stride; |
| 188 | + } |
| 189 | + |
| 190 | + cgltf_size safeCount = data->count; |
| 191 | + if (safeCount > maxCount) { |
| 192 | + LOG(WARNING) << "Skinning weights accessor count (" << safeCount |
| 193 | + << ") exceeds buffer capacity (" << maxCount |
| 194 | + << "), clamping to prevent out-of-bounds access."; |
| 195 | + safeCount = maxCount; |
| 196 | + } |
| 197 | + |
166 | 198 | uint8_t* bytes = (uint8_t*) data->buffer_view->buffer->data; |
167 | | - bytes += data->offset + data->buffer_view->offset; |
168 | | - for (cgltf_size i = 0, n = data->count; i < n; ++i, bytes += data->stride) { |
| 199 | + bytes += totalOffset; |
| 200 | + for (cgltf_size i = 0, n = safeCount; i < n; ++i, bytes += stride) { |
169 | 201 | float4* weights = (float4*) bytes; |
170 | 202 | const float sum = weights->x + weights->y + weights->z + weights->w; |
171 | 203 | *weights /= sum; |
@@ -243,8 +275,17 @@ inline void uploadBuffers(FFilamentAsset* asset, Engine& engine, |
243 | 275 |
|
244 | 276 | // For morph targets without buffer_view, use cgltf_accessor_unpack_floats to unpack data directly |
245 | 277 | if (!accessor->buffer_view && isMorphTarget) { |
246 | | - const size_t floatsCount = accessor->count * cgltf_num_components(accessor->type); |
| 278 | + const size_t components = cgltf_num_components(accessor->type); |
| 279 | + if (components > 0 && accessor->count > std::numeric_limits<size_t>::max() / components) { |
| 280 | + continue; |
| 281 | + } |
| 282 | + const size_t floatsCount = accessor->count * components; |
| 283 | + |
| 284 | + if (floatsCount > std::numeric_limits<size_t>::max() / sizeof(float)) { |
| 285 | + continue; |
| 286 | + } |
247 | 287 | const size_t floatsByteCount = sizeof(float) * floatsCount; |
| 288 | + |
248 | 289 | float* floatsData = (float*)malloc(floatsByteCount); |
249 | 290 | cgltf_accessor_unpack_floats(accessor, floatsData, floatsCount); |
250 | 291 |
|
@@ -279,8 +320,39 @@ inline void uploadBuffers(FFilamentAsset* asset, Engine& engine, |
279 | 320 | } |
280 | 321 | if (slot.vertexBuffer) { |
281 | 322 | if (utility::requiresConversion(accessor)) { |
282 | | - const size_t floatsCount = accessor->count * cgltf_num_components(accessor->type); |
| 323 | + const cgltf_size bufferSize = accessor->buffer_view->buffer->size; |
| 324 | + const cgltf_size totalOffset = accessor->buffer_view->offset + accessor->offset; |
| 325 | + |
| 326 | + if (totalOffset >= bufferSize) { |
| 327 | + continue; |
| 328 | + } |
| 329 | + |
| 330 | + const cgltf_size availableBytes = bufferSize - totalOffset; |
| 331 | + const cgltf_size stride = accessor->stride; |
| 332 | + const cgltf_size elementSize = cgltf_calc_size(accessor->type, accessor->component_type); |
| 333 | + |
| 334 | + cgltf_size maxCount = 0; |
| 335 | + if (stride > 0 && availableBytes >= elementSize) { |
| 336 | + maxCount = 1 + (availableBytes - elementSize) / stride; |
| 337 | + } |
| 338 | + |
| 339 | + cgltf_size safeCount = accessor->count; |
| 340 | + if (safeCount > maxCount) { |
| 341 | + LOG(WARNING) << "Accessor count exceeds buffer capacity, clamping."; |
| 342 | + safeCount = maxCount; |
| 343 | + } |
| 344 | + |
| 345 | + const size_t components = cgltf_num_components(accessor->type); |
| 346 | + if (components > 0 && safeCount > std::numeric_limits<size_t>::max() / components) { |
| 347 | + continue; |
| 348 | + } |
| 349 | + const size_t floatsCount = safeCount * components; |
| 350 | + |
| 351 | + if (floatsCount > std::numeric_limits<size_t>::max() / sizeof(float)) { |
| 352 | + continue; |
| 353 | + } |
283 | 354 | const size_t floatsByteCount = sizeof(float) * floatsCount; |
| 355 | + |
284 | 356 | float* floatsData = (float*) malloc(floatsByteCount); |
285 | 357 | cgltf_accessor_unpack_floats(accessor, floatsData, floatsCount); |
286 | 358 | BufferObject* bo = BufferObject::Builder().size(floatsByteCount).build(engine); |
@@ -317,8 +389,39 @@ inline void uploadBuffers(FFilamentAsset* asset, Engine& engine, |
317 | 389 | assert(slot.morphTargetBuffer); |
318 | 390 |
|
319 | 391 | if (utility::requiresPacking(accessor)) { |
320 | | - const size_t floatsCount = accessor->count * cgltf_num_components(accessor->type); |
| 392 | + const cgltf_size bufferSize = accessor->buffer_view->buffer->size; |
| 393 | + const cgltf_size totalOffset = accessor->buffer_view->offset + accessor->offset; |
| 394 | + |
| 395 | + if (totalOffset >= bufferSize) { |
| 396 | + continue; |
| 397 | + } |
| 398 | + |
| 399 | + const cgltf_size availableBytes = bufferSize - totalOffset; |
| 400 | + const cgltf_size stride = accessor->stride; |
| 401 | + const cgltf_size elementSize = cgltf_calc_size(accessor->type, accessor->component_type); |
| 402 | + |
| 403 | + cgltf_size maxCount = 0; |
| 404 | + if (stride > 0 && availableBytes >= elementSize) { |
| 405 | + maxCount = 1 + (availableBytes - elementSize) / stride; |
| 406 | + } |
| 407 | + |
| 408 | + cgltf_size safeCount = accessor->count; |
| 409 | + if (safeCount > maxCount) { |
| 410 | + LOG(WARNING) << "Accessor count exceeds buffer capacity, clamping."; |
| 411 | + safeCount = maxCount; |
| 412 | + } |
| 413 | + |
| 414 | + const size_t components = cgltf_num_components(accessor->type); |
| 415 | + if (components > 0 && safeCount > std::numeric_limits<size_t>::max() / components) { |
| 416 | + continue; |
| 417 | + } |
| 418 | + const size_t floatsCount = safeCount * components; |
| 419 | + |
| 420 | + if (floatsCount > std::numeric_limits<size_t>::max() / sizeof(float)) { |
| 421 | + continue; |
| 422 | + } |
321 | 423 | const size_t floatsByteCount = sizeof(float) * floatsCount; |
| 424 | + |
322 | 425 | float* floatsData = (float*) malloc(floatsByteCount); |
323 | 426 | cgltf_accessor_unpack_floats(accessor, floatsData, floatsCount); |
324 | 427 | if (accessor->type == cgltf_type_vec3) { |
|
0 commit comments