mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8373727: New XBM images parser regression: only the first line of the bitmap array is parsed
Reviewed-by: prr Backport-of: 7f707ba8e746d859ac171d71ef8f731953a92e6a
This commit is contained in:
parent
ffc6d1b74b
commit
d011d7c7cc
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -92,8 +92,8 @@ public class XbmImageDecoder extends ImageDecoder {
|
||||
byte[] raster = null;
|
||||
IndexColorModel model = null;
|
||||
|
||||
String matchRegex = "(0[xX])?[0-9a-fA-F]+[\\s+]?[,|};]";
|
||||
String replaceRegex = "(0[xX])|,|[\\s+]|[};]";
|
||||
String matchRegex = "\\s*(0[xX])?((?:(?!,|\\};).)+)(,|\\};)";
|
||||
String replaceRegex = "0[xX]|,|\\s+|\\};";
|
||||
|
||||
String line;
|
||||
int lineNum = 0;
|
||||
@ -111,11 +111,19 @@ public class XbmImageDecoder extends ImageDecoder {
|
||||
}
|
||||
try {
|
||||
if (!token[2].isBlank() && state == 0) {
|
||||
W = Integer.parseInt(token[2]);
|
||||
state = 1; // after width is set
|
||||
if (token[1].endsWith("th")) {
|
||||
W = Integer.parseInt(token[2]);
|
||||
} else if (token[1].endsWith("t")) {
|
||||
H = Integer.parseInt(token[2]);
|
||||
}
|
||||
state = 1; // after first dimension is set
|
||||
} else if (!token[2].isBlank() && state == 1) {
|
||||
H = Integer.parseInt(token[2]);
|
||||
state = 2; // after height is set
|
||||
if (token[1].endsWith("th")) {
|
||||
W = Integer.parseInt(token[2]);
|
||||
} else if (token[1].endsWith("t")) {
|
||||
H = Integer.parseInt(token[2]);
|
||||
}
|
||||
state = 2; // after second dimension is set
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
// parseInt() can throw NFE
|
||||
@ -147,59 +155,81 @@ public class XbmImageDecoder extends ImageDecoder {
|
||||
error("Width or Height of XBM file not defined");
|
||||
}
|
||||
|
||||
boolean contFlag = false;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// loop to process image data
|
||||
while (!aborted && (line = br.readLine()) != null) {
|
||||
lineNum++;
|
||||
|
||||
if (line.contains("[]")) {
|
||||
Matcher matcher = Pattern.compile(matchRegex).matcher(line);
|
||||
while (matcher.find()) {
|
||||
if (y >= H) {
|
||||
error("Scan size of XBM file exceeds"
|
||||
+ " the defined width x height");
|
||||
}
|
||||
|
||||
int startIndex = matcher.start();
|
||||
int endIndex = matcher.end();
|
||||
String hexByte = line.substring(startIndex, endIndex);
|
||||
|
||||
if (!(hexByte.startsWith("0x")
|
||||
|| hexByte.startsWith("0X"))) {
|
||||
error("Invalid hexadecimal number at Ln#:" + lineNum
|
||||
+ " Col#:" + (startIndex + 1));
|
||||
}
|
||||
hexByte = hexByte.replaceAll(replaceRegex, "");
|
||||
if (hexByte.length() != 2) {
|
||||
error("Invalid hexadecimal number at Ln#:" + lineNum
|
||||
+ " Col#:" + (startIndex + 1));
|
||||
}
|
||||
|
||||
try {
|
||||
n = Integer.parseInt(hexByte, 16);
|
||||
} catch (NumberFormatException nfe) {
|
||||
error("Error parsing hexadecimal at Ln#:" + lineNum
|
||||
+ " Col#:" + (startIndex + 1));
|
||||
}
|
||||
for (int mask = 1; mask <= 0x80; mask <<= 1) {
|
||||
if (x < W) {
|
||||
if ((n & mask) != 0)
|
||||
raster[x] = 1;
|
||||
else
|
||||
raster[x] = 0;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if (x >= W) {
|
||||
int result = setPixels(0, y, W, 1, model, raster, 0, W);
|
||||
if (result <= 0) {
|
||||
error("Unexpected error occurred during setPixel()");
|
||||
}
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
if (!contFlag) {
|
||||
if (line.contains("[]")) {
|
||||
contFlag = true;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int end = line.indexOf(';');
|
||||
if (end >= 0) {
|
||||
sb.append(line, 0, end + 1);
|
||||
break;
|
||||
} else {
|
||||
sb.append(line).append(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
String resultLine = sb.toString();
|
||||
int cutOffIndex = resultLine.indexOf('{');
|
||||
resultLine = resultLine.substring(cutOffIndex + 1);
|
||||
|
||||
Matcher matcher = Pattern.compile(matchRegex).matcher(resultLine);
|
||||
while (matcher.find()) {
|
||||
if (y >= H) {
|
||||
error("Scan size of XBM file exceeds"
|
||||
+ " the defined width x height");
|
||||
}
|
||||
|
||||
int startIndex = matcher.start();
|
||||
int endIndex = matcher.end();
|
||||
String hexByte = resultLine.substring(startIndex, endIndex);
|
||||
hexByte = hexByte.replaceAll("^\\s+", "");
|
||||
|
||||
if (!(hexByte.startsWith("0x")
|
||||
|| hexByte.startsWith("0X"))) {
|
||||
error("Invalid hexadecimal number at Ln#:" + lineNum
|
||||
+ " Col#:" + (startIndex + 1));
|
||||
}
|
||||
hexByte = hexByte.replaceAll(replaceRegex, "");
|
||||
if (hexByte.length() != 2) {
|
||||
error("Invalid hexadecimal number at Ln#:" + lineNum
|
||||
+ " Col#:" + (startIndex + 1));
|
||||
}
|
||||
|
||||
try {
|
||||
n = Integer.parseInt(hexByte, 16);
|
||||
} catch (NumberFormatException nfe) {
|
||||
error("Error parsing hexadecimal at Ln#:" + lineNum
|
||||
+ " Col#:" + (startIndex + 1));
|
||||
}
|
||||
for (int mask = 1; mask <= 0x80; mask <<= 1) {
|
||||
if (x < W) {
|
||||
if ((n & mask) != 0)
|
||||
raster[x] = 1;
|
||||
else
|
||||
raster[x] = 0;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if (x >= W) {
|
||||
int result = setPixels(0, y, W, 1, model, raster, 0, W);
|
||||
if (result <= 0) {
|
||||
error("Unexpected error occurred during setPixel()");
|
||||
}
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
imageComplete(ImageConsumer.STATICIMAGEDONE, true);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,10 +29,14 @@
|
||||
* @run main XBMDecoderTest
|
||||
*/
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
public class XBMDecoderTest {
|
||||
@ -57,21 +61,39 @@ public class XBMDecoderTest {
|
||||
|
||||
ImageIcon icon = new ImageIcon(fis.readAllBytes());
|
||||
boolean isErrEmpty = errContent.toString().isEmpty();
|
||||
|
||||
if (!isErrEmpty) {
|
||||
System.out.println("Expected ImageFormatException occurred.");
|
||||
System.out.print(errContent);
|
||||
}
|
||||
|
||||
if (validCase && !isErrEmpty) {
|
||||
throw new RuntimeException("Test failed: Error stream not empty");
|
||||
} else if (!validCase && isErrEmpty) {
|
||||
} else if (!validCase && isErrEmpty && hasPixelData(icon.getImage())) {
|
||||
throw new RuntimeException("Test failed: ImageFormatException"
|
||||
+ " expected but not thrown");
|
||||
}
|
||||
if (validCase && !hasPixelData(icon.getImage())) {
|
||||
throw new RuntimeException("Test failed: the parsed image " +
|
||||
"does not contain any pixel data");
|
||||
}
|
||||
System.out.println("PASSED\n");
|
||||
} finally {
|
||||
System.setErr(originalErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasPixelData(Image img) {
|
||||
int w = img.getWidth(null);
|
||||
int h = img.getHeight(null);
|
||||
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = bi.createGraphics();
|
||||
g.drawImage(img, 0, 0, null);
|
||||
g.dispose();
|
||||
int[] pixels = bi.getRGB(0, 0, w, h, null, 0, w);
|
||||
if (Arrays.stream(pixels).allMatch(i -> i == 0)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
6
test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm
Normal file
6
test/jdk/java/awt/image/XBMDecoder/invalid_empty.xbm
Normal file
@ -0,0 +1,6 @@
|
||||
#define test_width 16
|
||||
#define test_height 3
|
||||
#define ht_x 1
|
||||
#define ht_y 2
|
||||
static unsigned char test_bits[] = {
|
||||
};
|
||||
@ -1,3 +1,3 @@
|
||||
#define k_wt 16
|
||||
#define k_ht 1
|
||||
#define k_width 16
|
||||
#define k_height 1
|
||||
k[] = { 0x10, 1234567890};
|
||||
|
||||
3
test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm
Normal file
3
test/jdk/java/awt/image/XBMDecoder/invalid_plus.xbm
Normal file
@ -0,0 +1,3 @@
|
||||
#define test_width 16
|
||||
#define test_height 2
|
||||
static unsigned char test_bits[] = { 0x13, 0x11, 0xAB+, 0xff };
|
||||
8
test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm
Normal file
8
test/jdk/java/awt/image/XBMDecoder/valid_multiline.xbm
Normal file
@ -0,0 +1,8 @@
|
||||
#define test_width 16
|
||||
#define test_height 3
|
||||
#define ht_x 1
|
||||
#define ht_y 2
|
||||
static unsigned char test_bits[] = {
|
||||
0x20, 0x10,
|
||||
0x25, 0x01,
|
||||
0xAC, 0xab };
|
||||
Loading…
x
Reference in New Issue
Block a user