27
27
28
28
import jdk .internal .access .SharedSecrets ;
29
29
import jdk .internal .util .StaticProperty ;
30
- import sun .security .action .GetBooleanAction ;
31
30
32
31
import java .lang .reflect .InvocationTargetException ;
33
32
import java .security .AccessController ;
@@ -523,10 +522,15 @@ enum Status {
523
522
* {@systemProperty jdk.serialFilter}, its value is used to configure the filter.
524
523
* If the system property is not defined, and the {@link java.security.Security} property
525
524
* {@code jdk.serialFilter} is defined then it is used to configure the filter.
526
- * The filter is created as if {@link #createFilter(String) createFilter} is called;
527
- * if the filter string is invalid, an {@link ExceptionInInitializerError} is thrown.
528
- * Otherwise, the filter is not configured during initialization and
529
- * can be set with {@link #setSerialFilter(ObjectInputFilter) Config.setSerialFilter}.
525
+ * The filter is created as if {@link #createFilter(String) createFilter} is called,
526
+ * if the filter string is invalid the initialization fails and subsequent attempts to
527
+ * {@linkplain Config#getSerialFilter() get the filter}, {@linkplain Config#setSerialFilter set a filter},
528
+ * or create an {@linkplain ObjectInputStream#ObjectInputStream(InputStream) ObjectInputStream}
529
+ * throw {@link IllegalStateException}. Deserialization is not possible with an
530
+ * invalid serial filter.
531
+ * If the system property {@code jdk.serialFilter} or the {@link java.security.Security}
532
+ * property {@code jdk.serialFilter} is not set the filter can be set with
533
+ * {@link #setSerialFilter(ObjectInputFilter) Config.setSerialFilter}.
530
534
* Setting the {@code jdk.serialFilter} with {@link System#setProperty(String, String)
531
535
* System.setProperty} <em>does not set the filter</em>.
532
536
* The syntax for the property value is the same as for the
@@ -545,9 +549,12 @@ enum Status {
545
549
* <p>The class must be public, must have a public zero-argument constructor, implement the
546
550
* {@link BinaryOperator {@literal BinaryOperator<ObjectInputFilter>}} interface, provide its implementation and
547
551
* be accessible via the {@linkplain ClassLoader#getSystemClassLoader() application class loader}.
548
- * If the filter factory constructor is not invoked successfully, an {@link ExceptionInInitializerError}
549
- * is thrown and subsequent use of the filter factory for deserialization fails with
550
- * {@link IllegalStateException}.
552
+ * If the filter factory constructor is not invoked successfully subsequent attempts to
553
+ * {@linkplain Config#getSerialFilterFactory() get the factory},
554
+ * {@linkplain Config#setSerialFilterFactory(BinaryOperator) set the factory}, or create an
555
+ * {@link ObjectInputStream#ObjectInputStream(InputStream) ObjectInputStream}
556
+ * throw {@link IllegalStateException}. Deserialization is not possible with an
557
+ * invalid serial filter factory.
551
558
* The filter factory configured using the system or security property during initialization
552
559
* can NOT be replaced with {@link #setSerialFilterFactory(BinaryOperator) Config.setSerialFilterFactory}.
553
560
* This ensures that a filter factory set on the command line is not overridden accidentally
@@ -582,12 +589,22 @@ final class Config {
582
589
*/
583
590
private static volatile ObjectInputFilter serialFilter ;
584
591
592
+ /**
593
+ * Saved message if the jdk.serialFilter property is invalid.
594
+ */
595
+ private static final String invalidFilterMessage ;
596
+
585
597
/**
586
598
* Current serial filter factory.
587
599
* @see Config#setSerialFilterFactory(BinaryOperator)
588
600
*/
589
601
private static volatile BinaryOperator <ObjectInputFilter > serialFilterFactory ;
590
602
603
+ /**
604
+ * Saved message if the jdk.serialFilterFactory property is invalid.
605
+ */
606
+ private static final String invalidFactoryMessage ;
607
+
591
608
/**
592
609
* Boolean to indicate that the filter factory can not be set or replaced.
593
610
* - an ObjectInputStream has already been created using the current filter factory
@@ -630,23 +647,24 @@ final class Config {
630
647
Security .getProperty (SERIAL_FILTER_PROPNAME ));
631
648
632
649
// Initialize the static filter if the jdk.serialFilter is present
633
- ObjectInputFilter filter = null ;
650
+ String filterMessage = null ;
634
651
if (filterString != null ) {
635
652
configLog .log (DEBUG ,
636
653
"Creating deserialization filter from {0}" , filterString );
637
654
try {
638
- filter = createFilter (filterString );
655
+ serialFilter = createFilter (filterString );
639
656
} catch (RuntimeException re ) {
640
657
configLog .log (ERROR ,
641
658
"Error configuring filter: {0}" , (Object ) re );
642
- // Do not continue if configuration not initialized
643
- throw re ;
659
+ // serialFilter remains null
660
+ filterMessage = "Invalid jdk.serialFilter: " + re . getMessage () ;
644
661
}
645
662
}
646
- serialFilter = filter ;
663
+ invalidFilterMessage = filterMessage ;
647
664
648
665
// Initialize the filter factory if the jdk.serialFilterFactory is defined
649
666
// otherwise use the builtin filter factory.
667
+ String factoryMessage = null ;
650
668
if (factoryClassName == null ) {
651
669
serialFilterFactory = new BuiltinFilterFactory ();
652
670
} else {
@@ -671,10 +689,13 @@ final class Config {
671
689
Throwable th = (ex instanceof InvocationTargetException ite ) ? ite .getCause () : ex ;
672
690
configLog .log (ERROR ,
673
691
"Error configuring filter factory: {0}" , (Object )th );
674
- // Do not continue if configuration not initialized
675
- throw new ExceptionInInitializerError (th );
692
+ // Configuration not initialized
693
+ // serialFilterFactory remains null and filterFactoryNoReplace == true;
694
+ factoryMessage = "invalid jdk.serialFilterFactory: " +
695
+ factoryClassName + ": " + th .getClass ().getName () + ": " + th .getMessage ();
676
696
}
677
697
}
698
+ invalidFactoryMessage = factoryMessage ;
678
699
// Setup shared secrets for RegistryImpl to use.
679
700
SharedSecrets .setJavaObjectInputFilterAccess (Config ::createFilter2 );
680
701
}
@@ -696,8 +717,14 @@ private static void traceFilter(String msg, Object... args) {
696
717
* Returns the static JVM-wide deserialization filter or {@code null} if not configured.
697
718
*
698
719
* @return the static JVM-wide deserialization filter or {@code null} if not configured
720
+ * @throws IllegalStateException if the initialization of the filter from the
721
+ * system property {@code jdk.serialFilter} or
722
+ * the security property {@code jdk.serialFilter} fails.
699
723
*/
700
724
public static ObjectInputFilter getSerialFilter () {
725
+ if (invalidFilterMessage != null ) {
726
+ throw new IllegalStateException (invalidFilterMessage );
727
+ }
701
728
return serialFilter ;
702
729
}
703
730
@@ -707,7 +734,9 @@ public static ObjectInputFilter getSerialFilter() {
707
734
* @param filter the deserialization filter to set as the JVM-wide filter; not null
708
735
* @throws SecurityException if there is security manager and the
709
736
* {@code SerializablePermission("serialFilter")} is not granted
710
- * @throws IllegalStateException if the filter has already been set
737
+ * @throws IllegalStateException if the filter has already been set or the initialization
738
+ * of the filter from the system property {@code jdk.serialFilter} or
739
+ * the security property {@code jdk.serialFilter} fails.
711
740
*/
712
741
public static void setSerialFilter (ObjectInputFilter filter ) {
713
742
Objects .requireNonNull (filter , "filter" );
@@ -716,6 +745,9 @@ public static void setSerialFilter(ObjectInputFilter filter) {
716
745
if (sm != null ) {
717
746
sm .checkPermission (ObjectStreamConstants .SERIAL_FILTER_PERMISSION );
718
747
}
748
+ if (invalidFilterMessage != null ) {
749
+ throw new IllegalStateException (invalidFilterMessage );
750
+ }
719
751
synchronized (serialFilterLock ) {
720
752
if (serialFilter != null ) {
721
753
throw new IllegalStateException ("Serial filter can only be set once" );
@@ -749,8 +781,10 @@ public static void setSerialFilter(ObjectInputFilter filter) {
749
781
* @since 17
750
782
*/
751
783
public static BinaryOperator <ObjectInputFilter > getSerialFilterFactory () {
752
- if (serialFilterFactory == null )
753
- throw new IllegalStateException ("Serial filter factory initialization incomplete" );
784
+ if (serialFilterFactory == null ) {
785
+ // If initializing the factory failed or not yet complete, throw with the message
786
+ throw new IllegalStateException (invalidFilterFactoryMessage ());
787
+ }
754
788
return serialFilterFactory ;
755
789
}
756
790
@@ -812,15 +846,26 @@ public static void setSerialFilterFactory(BinaryOperator<ObjectInputFilter> filt
812
846
}
813
847
if (filterFactoryNoReplace .getAndSet (true )) {
814
848
final String msg = serialFilterFactory != null
815
- ? serialFilterFactory .getClass ().getName ()
816
- : "initialization incomplete" ;
817
- throw new IllegalStateException ("Cannot replace filter factory: " + msg );
849
+ ? "Cannot replace filter factory: " + serialFilterFactory .getClass ().getName ()
850
+ : invalidFilterFactoryMessage () ;
851
+ throw new IllegalStateException (msg );
818
852
}
819
853
configLog .log (DEBUG ,
820
854
"Setting deserialization filter factory to {0}" , filterFactory .getClass ().getName ());
821
855
serialFilterFactory = filterFactory ;
822
856
}
823
857
858
+ /*
859
+ * Return message for an invalid filter factory configuration saved from the static init.
860
+ * It can be called before the static initializer is complete and has set the message/null.
861
+ */
862
+ private static String invalidFilterFactoryMessage () {
863
+ assert serialFilterFactory == null ; // undefined if a filter factory has been set
864
+ return (invalidFactoryMessage != null )
865
+ ? invalidFactoryMessage
866
+ : "Serial filter factory initialization incomplete" ;
867
+ }
868
+
824
869
/**
825
870
* Returns an ObjectInputFilter from a string of patterns.
826
871
* <p>
0 commit comments