Last active
January 18, 2025 15:07
-
-
Save asdf913/aefc815914c11c625c418e7d56674828 to your computer and use it in GitHub Desktop.
List of allowed "org.apache.pdfbox.util.filetypedetector.FileType" and test if a given file is accepted by "org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.createFromByteArray(org.apache.pdfbox.pdmodel.PDDocument,byte[],java.lang.String)" method
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Member; | |
import java.lang.reflect.Method; | |
import java.lang.reflect.Proxy; | |
import java.nio.file.Files; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Collection; | |
import java.util.List; | |
import java.util.Map.Entry; | |
import java.util.Objects; | |
import java.util.function.Predicate; | |
import java.util.stream.Stream; | |
import org.apache.bcel.classfile.ClassParser; | |
import org.apache.bcel.classfile.ConstantPool; | |
import org.apache.bcel.classfile.FieldOrMethod; | |
import org.apache.bcel.classfile.JavaClass; | |
import org.apache.bcel.generic.ConstantPoolGen; | |
import org.apache.bcel.generic.FieldInstruction; | |
import org.apache.bcel.generic.GETSTATIC; | |
import org.apache.bcel.generic.IF_ACMPEQ; | |
import org.apache.bcel.generic.IF_ACMPNE; | |
import org.apache.bcel.generic.INVOKESTATIC; | |
import org.apache.bcel.generic.Instruction; | |
import org.apache.bcel.generic.InstructionList; | |
import org.apache.bcel.generic.InvokeInstruction; | |
import org.apache.bcel.generic.MethodGen; | |
import org.apache.bcel.generic.Type; | |
import org.apache.commons.collections4.IterableUtils; | |
import org.apache.commons.lang3.ArrayUtils; | |
import org.apache.commons.lang3.ObjectUtils; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.commons.lang3.function.FailableFunction; | |
import org.apache.commons.lang3.reflect.FieldUtils; | |
import org.apache.commons.lang3.tuple.MutablePair; | |
import org.apache.pdfbox.pdmodel.PDDocument; | |
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; | |
public class PDImageXObjectTest { | |
public static void main(final String[] args) | |
throws NoSuchMethodException, IOException, IllegalAccessException, InvocationTargetException { | |
// | |
final Entry<Method, Collection<Object>> entry = getPDImageXObjectCreateFromByteArrayDetectFileTypeMethodAndAllowedFileTypes(); | |
// | |
System.out.println(entry); | |
// | |
// (public static org.apache.pdfbox.util.filetypedetector.FileType | |
// org.apache.pdfbox.util.filetypedetector.FileTypeDetector.detectFileType(byte[]),[JPEG, | |
// PNG, TIFF, BMP, GIF]) | |
// | |
if (args != null && args.length > 0 && entry != null) { | |
// | |
final File file = new File(args[0]); | |
// | |
System.out.println(); | |
// | |
final Object object = entry.getKey().invoke(null, Files.readAllBytes(file.toPath())); | |
// | |
System.out.println(object); | |
// | |
System.out.println(entry.getValue().contains(object)); | |
// | |
} // if | |
// | |
} | |
private static Entry<Method, Collection<Object>> getPDImageXObjectCreateFromByteArrayDetectFileTypeMethodAndAllowedFileTypes() | |
throws IOException, NoSuchMethodException, IllegalAccessException { | |
// | |
Class<?> clz = PDImageXObject.class; | |
// | |
Collection<Object> allowedFileType = null; | |
// | |
MutablePair<Method, Collection<Object>> entry = null; | |
// | |
try (final InputStream is = getResourceAsStream(clz, | |
String.format("/%1$s.class", StringUtils.replace(getName(clz), ".", "/")))) { | |
// | |
// org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.createFromByteArray(org.apache.pdfbox.pdmodel.PDDocument,byte[],java.lang.String) | |
// | |
final org.apache.bcel.classfile.Method m = getMethod( | |
parse(testAndApply(Objects::nonNull, is, x -> new ClassParser(x, null), null)), | |
getDeclaredMethod(clz, "createFromByteArray", PDDocument.class, byte[].class, String.class)); | |
// | |
final Instruction[] ins = getInstructions( | |
getInstructionList(testAndApply(Objects::nonNull, m, x -> new MethodGen(x, null, null), null))); | |
// | |
final ConstantPool cp = getConstantPool(m); | |
// | |
final ConstantPoolGen cpg = new ConstantPoolGen(cp); | |
// | |
Instruction in = null; | |
// | |
INVOKESTATIC invokestatic = null; | |
// | |
Object object = null; | |
// | |
Type[] argumentTypes = null; | |
// | |
List<Field> fs = null; | |
// | |
int size = 0; | |
// | |
for (int i = 0; i < length(ins); i++) { | |
// | |
if ((in = ArrayUtils.get(ins, i)) instanceof INVOKESTATIC temp && invokestatic == null) { | |
// | |
if (length((argumentTypes = getArgumentTypes(invokestatic = temp, cpg))) == 1) { | |
// | |
if ((entry = ObjectUtils.getIfNull(entry, MutablePair::new)) != null) { | |
// | |
entry.setLeft(getDeclaredMethod(clz = forName(getClassName(invokestatic, cpg)), | |
getMethodName(invokestatic, cpg), | |
forName(getClassName(ArrayUtils.get(argumentTypes, 0))))); | |
// | |
} // if | |
// | |
} // if | |
// | |
} else if (i > 0 && ArrayUtils.get(ins, i - 1) instanceof GETSTATIC getstatic | |
&& Boolean.logicalOr(in instanceof IF_ACMPNE, in instanceof IF_ACMPEQ)) { | |
// | |
if ((size = IterableUtils.size(fs = toList( | |
filter(Arrays.stream(getDeclaredFields(forName(getClassName(getstatic.getFieldType(cpg))))), | |
f -> Objects.equals(getName(f), getFieldName(getstatic, cpg)))))) > 1) { | |
// | |
throw new IllegalStateException(); | |
// | |
} else if (size == 1) { | |
// | |
if (!contains(allowedFileType = ObjectUtils.getIfNull(allowedFileType, ArrayList::new), | |
object = FieldUtils.readStaticField(IterableUtils.get(fs, 0)))) { | |
// | |
add(allowedFileType, object); | |
// | |
} // if | |
// | |
} // if | |
// | |
} // if | |
// | |
} // for | |
// | |
} // try | |
// | |
if ((entry = ObjectUtils.getIfNull(entry, MutablePair::new)) != null) { | |
// | |
entry.setValue(allowedFileType); | |
// | |
} // if | |
// | |
return entry; | |
// | |
} | |
private static ConstantPool getConstantPool(final FieldOrMethod instance) { | |
return instance != null ? instance.getConstantPool() : null; | |
} | |
private static String getFieldName(final FieldInstruction instance, final ConstantPoolGen cpg) { | |
return instance != null ? instance.getFieldName(cpg) : null; | |
} | |
private static String getClassName(final Type instance) { | |
return instance != null ? instance.getClassName() : null; | |
} | |
private static String getMethodName(final InvokeInstruction instance, final ConstantPoolGen cpg) { | |
return instance != null ? instance.getMethodName(cpg) : null; | |
} | |
private static String getClassName(final InvokeInstruction instance, final ConstantPoolGen cpg) { | |
return instance != null ? instance.getClassName(cpg) : null; | |
} | |
private static Type[] getArgumentTypes(final InvokeInstruction instance, final ConstantPoolGen cpg) { | |
return instance != null ? instance.getArgumentTypes(cpg) : null; | |
} | |
private static InstructionList getInstructionList(final MethodGen instance) { | |
return instance != null ? instance.getInstructionList() : null; | |
} | |
private static org.apache.bcel.classfile.Method getMethod(final JavaClass instance, | |
final java.lang.reflect.Method m) { | |
return instance != null ? instance.getMethod(m) : null; | |
} | |
private static <E> void add(final Collection<E> items, final E item) { | |
if (items != null) { | |
items.add(item); | |
} | |
} | |
private static boolean contains(final Collection<?> items, final Object item) { | |
return items != null && items.contains(item); | |
} | |
private static Instruction[] getInstructions(final InstructionList instance) { | |
return instance != null ? instance.getInstructions() : null; | |
} | |
private static JavaClass parse(final ClassParser instance) throws IOException { | |
return instance != null ? instance.parse() : null; | |
} | |
private static <T> List<T> toList(final Stream<T> instance) { | |
return instance != null ? instance.toList() : null; | |
} | |
private static <T> Stream<T> filter(final Stream<T> instance, final Predicate<? super T> predicate) { | |
// | |
return instance != null && (predicate != null || Proxy.isProxyClass(getClass(instance))) | |
? instance.filter(predicate) | |
: null; | |
// | |
} | |
private static Class<?> getClass(final Object instance) { | |
return instance != null ? instance.getClass() : null; | |
} | |
private static Class<?> forName(final String className) { | |
try { | |
return StringUtils.isNotBlank(className) ? Class.forName(className) : null; | |
} catch (final ClassNotFoundException e) { | |
return null; | |
} | |
} | |
private static int length(final Object[] instance) { | |
return instance != null ? instance.length : 0; | |
} | |
private static <T, R, E extends Throwable> R testAndApply(final Predicate<T> predicate, final T value, | |
final FailableFunction<T, R, E> functionTrue, final FailableFunction<T, R, E> functionFalse) throws E { | |
return test(predicate, value) ? apply(functionTrue, value) : apply(functionFalse, value); | |
} | |
private static <T, R, E extends Throwable> R apply(final FailableFunction<T, R, E> instance, final T value) | |
throws E { | |
return instance != null ? instance.apply(value) : null; | |
} | |
private static final <T> boolean test(final Predicate<T> instance, final T value) { | |
return instance != null && instance.test(value); | |
} | |
private static Field[] getDeclaredFields(final Class<?> instance) { | |
return instance != null ? instance.getDeclaredFields() : null; | |
} | |
private static Method getDeclaredMethod(final Class<?> instance, final String name, | |
final Class<?>... parameterTypes) throws NoSuchMethodException { | |
return instance != null ? instance.getDeclaredMethod(name, parameterTypes) : null; | |
} | |
private static String getName(final Class<?> instance) { | |
return instance != null ? instance.getName() : null; | |
} | |
private static String getName(final Member instance) { | |
return instance != null ? instance.getName() : null; | |
} | |
private static InputStream getResourceAsStream(final Class<?> instance, final String name) { | |
return instance != null && name != null ? instance.getResourceAsStream(name) : null; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependencies> | |
<!-- https://mvnrepository.com/artifact/org.apache.bcel/bcel --> | |
<dependency> | |
<groupId>org.apache.bcel</groupId> | |
<artifactId>bcel</artifactId> | |
<version>6.10.0</version> | |
</dependency> | |
<!--https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 --> | |
<dependency> | |
<groupId>org.apache.commons</groupId> | |
<artifactId>commons-collections4</artifactId> | |
<version>4.4</version> | |
</dependency> | |
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox --> | |
<dependency> | |
<groupId>org.apache.pdfbox</groupId> | |
<artifactId>pdfbox</artifactId> | |
<version>3.0.3</version> | |
</dependency> | |
</dependencies> |
Author
asdf913
commented
Jan 18, 2025
•
Method | public static org.apache.pdfbox.util.filetypedetector.FileType org.apache.pdfbox.util.filetypedetector.FileTypeDetector.detectFileType(byte[]) |
---|---|
Allowed File Type | [JPEG, PNG, TIFF, BMP, GIF] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment