Skip to content

Commit 7c8aad1

Browse files
authored
Issue #12453 - AnnotationParser NPE protection (#13162)
+ Better utilize Resource object, don't rely on Path existing for things that don't require Path.
1 parent b559bba commit 7c8aad1

File tree

3 files changed

+82
-17
lines changed
  • jetty-core
  • jetty-ee9/jetty-ee9-osgi/jetty-ee9-osgi-boot/src/main/java/org/eclipse/jetty/ee9/osgi/annotations

3 files changed

+82
-17
lines changed

jetty-core/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.Set;
2626
import java.util.concurrent.ConcurrentHashMap;
2727

28+
import org.eclipse.jetty.io.IOResources;
2829
import org.eclipse.jetty.util.ExceptionUtil;
2930
import org.eclipse.jetty.util.FileID;
3031
import org.eclipse.jetty.util.StringUtil;
@@ -606,7 +607,7 @@ protected void parseDir(Set<? extends Handler> handlers, Resource dirResource) t
606607

607608
try
608609
{
609-
parseClass(handlers, dirResource, candidate.getPath());
610+
parseClass(handlers, dirResource, candidate);
610611
}
611612
catch (Exception ex)
612613
{
@@ -629,9 +630,6 @@ protected void parseJar(Set<? extends Handler> handlers, Resource jarResource) t
629630
if (jarResource == null)
630631
return;
631632

632-
/* if (!FileID.isJavaArchive(jarResource.getPath()))
633-
return;*/
634-
635633
if (LOG.isDebugEnabled())
636634
LOG.debug("Scanning jar {}", jarResource);
637635

@@ -649,27 +647,60 @@ protected void parseJar(Set<? extends Handler> handlers, Resource jarResource) t
649647
* @param containingResource the dir or jar that the class is contained within, can be null if not known
650648
* @param classFile the class file to parse
651649
* @throws IOException if unable to parse
650+
* @deprecated use {@link #parseClass(Set, Resource, Resource)} instead (which uses {@link Resource} instead of {@link Path})
652651
*/
652+
@Deprecated(since = "12.0.21", forRemoval = true)
653653
protected void parseClass(Set<? extends Handler> handlers, Resource containingResource, Path classFile) throws IOException
654654
{
655-
if (LOG.isDebugEnabled())
656-
LOG.debug("Parse class from {}", classFile.toUri());
655+
try (InputStream inputStream = Files.newInputStream(classFile))
656+
{
657+
parseClass(handlers, containingResource, classFile.toUri(), inputStream);
658+
}
659+
}
660+
661+
/**
662+
* Use ASM on a class
663+
*
664+
* @param handlers the handlers to look for classes in
665+
* @param containingResource the dir or jar that the class is contained within, can be null if not known
666+
* @param classFile the class file to parse
667+
* @throws IOException if unable to parse
668+
*/
669+
protected void parseClass(Set<? extends Handler> handlers, Resource containingResource, Resource classFile) throws IOException
670+
{
671+
try (InputStream inputStream = IOResources.asInputStream(classFile))
672+
{
673+
parseClass(handlers, containingResource, classFile.getURI(), inputStream);
674+
}
675+
}
657676

658-
URI location = classFile.toUri();
677+
/**
678+
* Use ASM on a class
679+
*
680+
* @param handlers the handlers to look for classes in
681+
* @param containingResource the dir or jar that the class is contained within, can be null if not known
682+
* @param classFileRef the URI reference to the classfile location
683+
* @param inputStream the class file contents to parse
684+
* @throws IOException if unable to parse
685+
*/
686+
private void parseClass(Set<? extends Handler> handlers, Resource containingResource, URI classFileRef, InputStream inputStream) throws IOException
687+
{
688+
if (LOG.isDebugEnabled())
689+
LOG.debug("Parse class from {}", classFileRef);
659690

660-
try (InputStream in = Files.newInputStream(classFile))
691+
try
661692
{
662-
ClassReader reader = new ClassReader(in);
693+
ClassReader reader = new ClassReader(inputStream);
663694
reader.accept(new MyClassVisitor(handlers, containingResource, _asmVersion), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
664695

665696
String classname = normalize(reader.getClassName());
666-
URI existing = _parsedClassNames.putIfAbsent(classname, location);
697+
URI existing = _parsedClassNames.putIfAbsent(classname, classFileRef);
667698
if (existing != null)
668-
LOG.warn("{} scanned from multiple locations: {}, {}", classname, existing, location);
699+
LOG.warn("{} scanned from multiple locations: {}, {}", classname, existing, classFileRef);
669700
}
670701
catch (IllegalArgumentException | IOException e)
671702
{
672-
throw new IOException("Unable to parse class: " + classFile.toUri(), e);
703+
throw new IOException("Unable to parse class: " + classFileRef, e);
673704
}
674705
}
675706

jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/FileID.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.nio.file.Files;
2020
import java.nio.file.Path;
2121
import java.util.Locale;
22+
import java.util.Objects;
2223
import java.util.regex.Pattern;
2324

2425
/**
@@ -38,6 +39,7 @@ public class FileID
3839
*/
3940
public static String getBasename(Path path)
4041
{
42+
Objects.requireNonNull(path);
4143
Path filename = path.getFileName();
4244
if (filename == null)
4345
return "";
@@ -378,11 +380,27 @@ public static boolean isLibArchive(URI uri)
378380
*/
379381
public static boolean isClassFile(Path path)
380382
{
383+
if (path == null)
384+
return false;
385+
381386
Path fileNamePath = path.getFileName();
382387
if (fileNamePath == null)
383388
return false;
384-
385-
String filename = fileNamePath.toString();
389+
390+
return isClassFile(fileNamePath.toString());
391+
}
392+
393+
/**
394+
* Predicate to test for class files
395+
*
396+
* @param filename the filename to test
397+
* @return true if the filename ends with {@code .class}
398+
*/
399+
public static boolean isClassFile(String filename)
400+
{
401+
if (StringUtil.isBlank(filename))
402+
return false;
403+
386404
// has to end in ".class"
387405
if (!StringUtil.asciiEndsWithIgnoreCase(filename, ".class"))
388406
return false;
@@ -416,6 +434,9 @@ public static boolean isClassFile(Path path)
416434
*/
417435
public static boolean isHidden(Path path)
418436
{
437+
if (path == null)
438+
return false;
439+
419440
int count = path.getNameCount();
420441
for (int i = 0; i < count; i++)
421442
{
@@ -455,6 +476,9 @@ public static boolean isHidden(Path path)
455476
*/
456477
public static boolean isHidden(Path base, Path path)
457478
{
479+
if (base == null || path == null)
480+
return false;
481+
458482
// Work with the path in relative form, from the base onwards to the path
459483
return isHidden(base.relativize(path));
460484
}
@@ -504,6 +528,9 @@ public static boolean isJavaArchive(String filename)
504528
*/
505529
public static boolean isMetaInfVersions(Path path)
506530
{
531+
if (path == null)
532+
return false;
533+
507534
if (path.getNameCount() < 3)
508535
return false;
509536

@@ -543,6 +570,9 @@ public static boolean isNotMetaInfVersions(Path path)
543570
*/
544571
public static boolean isModuleInfoClass(Path path)
545572
{
573+
if (path == null)
574+
return false;
575+
546576
Path filenameSegment = path.getFileName();
547577
if (filenameSegment == null)
548578
return false;

jetty-ee9/jetty-ee9-osgi/jetty-ee9-osgi-boot/src/main/java/org/eclipse/jetty/ee9/osgi/annotations/AnnotationParser.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.eclipse.jetty.osgi.BundleIndex;
2121
import org.eclipse.jetty.util.FileID;
2222
import org.eclipse.jetty.util.resource.Resource;
23+
import org.eclipse.jetty.util.resource.Resources;
2324
import org.osgi.framework.Bundle;
2425
import org.slf4j.Logger;
2526
import org.slf4j.LoggerFactory;
@@ -66,6 +67,9 @@ public void parse(final Set<? extends Handler> handlers, Resource r) throws Exce
6667
if (r == null)
6768
return;
6869

70+
if (!Resources.exists(r))
71+
return;
72+
6973
if (FileID.isJavaArchive(r.getPath()))
7074
{
7175
parseJar(handlers, r);
@@ -80,11 +84,11 @@ public void parse(final Set<? extends Handler> handlers, Resource r) throws Exce
8084

8185
if (FileID.isClassFile(r.getPath()))
8286
{
83-
parseClass(handlers, null, r.getPath());
87+
parseClass(handlers, null, r);
8488
}
8589

86-
//Not already parsed, it could be a file that actually is compressed but does not have
87-
//.jar/.zip etc extension, such as equinox urls, so try to parse it
90+
// Not already parsed, it could be a file that actually is compressed but does not have
91+
// .jar/.zip etc extension, such as equinox urls, so try to parse it
8892
try
8993
{
9094
parseJar(handlers, r);

0 commit comments

Comments
 (0)