java-topology/defects/imagemagick/unit/ImageMagickTest.java

164 lines
5.4 KiB
Java

/**
* CWE-407 simulation tests for ImageMagick defects.
*
* imagemagick-0001: UHDR coder GetImageListLength() O(N) called N times in loop = O(N^2)
* imagemagick-0002: SyncImageList nested loop scene-number duplicate check = O(N^2)
*/
public class ImageMagickTest {
// ---------------------------------------------------------------
// imagemagick-0001: UHDR GetImageListLength in loop
// ---------------------------------------------------------------
/** Simulate a doubly-linked image list */
static class ImageNode {
int scene;
int depth;
ImageNode next;
ImageNode previous;
ImageNode(int scene, int depth) {
this.scene = scene;
this.depth = depth;
}
}
static ImageNode buildImageList(int n) {
ImageNode head = new ImageNode(0, 8);
ImageNode prev = head;
for (int i = 1; i < n; i++) {
ImageNode node = new ImageNode(i, 8);
node.previous = prev;
prev.next = node;
prev = node;
}
return head;
}
/** O(N) traversal — simulates GetImageListLength */
static int getImageListLength(ImageNode image) {
// Go to end first
ImageNode p = image;
while (p.next != null) p = p.next;
// Count backwards
int count = 0;
while (p != null) {
count++;
p = p.previous;
}
return count;
}
/** DEFECTIVE: calls getImageListLength inside loop = O(N^2) */
static long writeUhdrDefective(ImageNode image) {
long ops = 0;
for (int i = 0; i < getImageListLength(image); i++) {
ops += getImageListLength(image); // count traversal ops
// simulate per-frame work
if (image.next != null) image = image.next;
}
return ops;
}
/** FIXED: cache length before loop = O(N) */
static long writeUhdrFixed(ImageNode image) {
long ops = 0;
int numberScenes = getImageListLength(image);
ops += numberScenes; // one traversal
for (int i = 0; i < numberScenes; i++) {
ops++; // per-frame work
if (image.next != null) image = image.next;
}
return ops;
}
static void testUhdrGetImageListLength() {
int N = 500;
ImageNode list = buildImageList(N);
long defectOps = writeUhdrDefective(list);
long fixedOps = writeUhdrFixed(buildImageList(N));
double ratio = (double) defectOps / fixedOps;
System.out.printf("imagemagick-0001 UHDR GetImageListLength in loop:%n");
System.out.printf(" N=%d defect_ops=%d fixed_ops=%d ratio=%.1fx%n",
N, defectOps, fixedOps, ratio);
assert ratio > 50.0 : "Expected significant overhead ratio, got " + ratio;
System.out.println(" PASS");
}
// ---------------------------------------------------------------
// imagemagick-0002: SyncImageList O(N^2) scene dedup
// ---------------------------------------------------------------
/** DEFECTIVE: nested loop duplicate scene check O(N^2) */
static long syncImageListDefective(ImageNode images) {
long ops = 0;
ImageNode p, q;
boolean hasDup = false;
for (p = images; p != null; p = p.next) {
for (q = p.next; q != null; q = q.next) {
ops++;
if (p.scene == q.scene) {
hasDup = true;
break;
}
}
if (hasDup) break;
}
if (!hasDup) {
// scenes are unique — no renumbering needed (worst case: full scan)
}
return ops;
}
/** FIXED: single-pass sequential check O(N) */
static long syncImageListFixed(ImageNode images) {
long ops = 0;
if (images == null || images.next == null) return 0;
boolean needsRenumber = false;
int expected = images.scene;
for (ImageNode p = images.next; p != null; p = p.next) {
ops++;
expected++;
if (p.scene != expected) {
needsRenumber = true;
break;
}
}
if (needsRenumber) {
for (ImageNode p = images.next; p != null; p = p.next) {
ops++;
p.scene = p.previous.scene + 1;
}
}
return ops;
}
static void testSyncImageListDedup() {
int N = 1000;
// Build list with unique sequential scenes (worst case for defective)
ImageNode list = buildImageList(N);
long defectOps = syncImageListDefective(list);
ImageNode list2 = buildImageList(N);
long fixedOps = syncImageListFixed(list2);
double ratio = (double) defectOps / fixedOps;
System.out.printf("imagemagick-0002 SyncImageList scene dedup:%n");
System.out.printf(" N=%d defect_ops=%d fixed_ops=%d ratio=%.1fx%n",
N, defectOps, fixedOps, ratio);
assert ratio > 100.0 : "Expected significant overhead ratio, got " + ratio;
System.out.println(" PASS");
}
// ---------------------------------------------------------------
// Main
// ---------------------------------------------------------------
public static void main(String[] args) {
testUhdrGetImageListLength();
testSyncImageListDedup();
System.out.println("\nAll ImageMagick CWE-407 tests PASS");
}
}