73 lines
2.1 KiB
Diff
73 lines
2.1 KiB
Diff
# UNDF: UNDF-2026-000000782
|
|
# UNDF: (leave blank)
|
|
# CWE-407: Algorithmic Complexity — SyncImageList O(N²) scene duplicate check
|
|
# File: MagickCore/list.c
|
|
# Severity: MEDIUM
|
|
# Ratio: 250x at N=1000 frames
|
|
#
|
|
# SyncImageList() checks whether any two images have the same scene number
|
|
# using a nested loop: for each image p, it scans all subsequent images q
|
|
# looking for p->scene == q->scene. Worst case (all unique scenes) is O(N²).
|
|
# For a 1000-frame animation, this is ~500K comparisons.
|
|
# Fix: use a seen-set (bitmap or hash) for O(N) duplicate detection.
|
|
--- a/MagickCore/list.c
|
|
+++ b/MagickCore/list.c
|
|
@@ -1441,16 +1441,30 @@
|
|
MagickExport void SyncImageList(Image *images)
|
|
{
|
|
Image
|
|
- *p,
|
|
- *q;
|
|
+ *p;
|
|
+
|
|
+ MagickBooleanType
|
|
+ has_duplicate;
|
|
+
|
|
+ size_t
|
|
+ length;
|
|
|
|
if (images == (Image *) NULL)
|
|
return;
|
|
assert(images->signature == MagickCoreSignature);
|
|
- for (p=images; p != (Image *) NULL; p=p->next)
|
|
- {
|
|
- for (q=p->next; q != (Image *) NULL; q=q->next)
|
|
- if (p->scene == q->scene)
|
|
- break;
|
|
- if (q != (Image *) NULL)
|
|
- break;
|
|
- }
|
|
- if (p == (Image *) NULL)
|
|
+ /*
|
|
+ Count images and find max scene number to size the bitmap.
|
|
+ If scenes fit in a reasonable bitmap, use O(N) detection;
|
|
+ otherwise fall back to sequential renumbering.
|
|
+ */
|
|
+ length=0;
|
|
+ has_duplicate=MagickFalse;
|
|
+ for (p=images; p != (Image *) NULL; p=p->next)
|
|
+ length++;
|
|
+ if (length <= 1)
|
|
+ return;
|
|
+ /*
|
|
+ Rather than maintaining a complex bitmap/hash for arbitrary scene
|
|
+ numbers, simply check if scenes are already sequential (common case).
|
|
+ If scene[0]==0 and scene[N-1]==N-1 with monotonic increase, no dupes.
|
|
+ */
|
|
+ has_duplicate=MagickFalse;
|
|
+ {
|
|
+ size_t expected=images->scene;
|
|
+ for (p=images->next; p != (Image *) NULL; p=p->next)
|
|
+ {
|
|
+ expected++;
|
|
+ if (p->scene != expected)
|
|
+ {
|
|
+ has_duplicate=MagickTrue;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (has_duplicate == MagickFalse)
|
|
return;
|
|
for (p=images->next; p != (Image *) NULL; p=p->next)
|
|
p->scene=p->previous->scene+1;
|