[OpenJDK 2D-Dev] [9] RFR JDK-6278300: sun.print.Win32MediaSize deserialization error

Phil Race philip.race at oracle.com
Mon Jul 25 20:24:06 UTC 2016


The fix seems wrong to me .. and the problem is not easy.

Windows defines standard paper sizes and we recognise those and will 
always serialise
the "Media" as one of the built-in java pre-defined Media.

But windows printer drivers very  typically define additional 
driver-specific papers,
so at runtime JDK dynamically creates new instances as these are discovered.

They will be instances of Win32MediaSize and their IDs (enum int values) 
will
be entirely dependent on the order they "happened" to be added to the list.

When you serialise this out, all you serialise is
(a) the type (Win32MediaSize) and (b) the int value (see the serialized 
form docs
for EnumSyntax).

When you come to *deserialize* then what happens depends on whether the
code that adds those to the list has been run (or not). If it has, you 
may well
be lucky and get the right intended paper.

If it has not - which is inevitable if you load the preferences in main(..)
before any printing code has run - then the code that initialises the table
has not been run and the int value is meaningless. Pointing it to the ID
in the super-class is wrong. Also you have not run the Win32MediaSize
constructor ! So you will have deserialized a garbage instance .. it
will have an ID that does not correspond to the table, and was meant
to ID some standard paper size. So the fix is probably worse than the bug.

It seems like there should be a readResolve() for Win32MediaSize that
first initialises the table.

And it is only *this simple* (yes, I mean that) because you only have one
printer involved. Get 4 printers with custom IDs and you don't even know
in which order these printers had their IDs initialised.

The  documented serialised form leaves you with essentially insufficient 
information.
It seems like Win32MediaSize needs a serialised form that includes the 
extra info.
But if you "delete" the printer and run the app you now have useless 
serialised data
and need to esstablish a policy around that.

Also it seems likely we have the same issue in the CUPS code ..

This is a non-trivial bug and will likely take a lot of careful work to
figure out all the spec/compat/behavioural issues.


-phil.





On 07/15/2016 02:36 AM, Prasanta Sadhukhan wrote:
> Hi All,
>
> Bug: https://bugs.openjdk.java.net/browse/JDK-6278300
>
> Please review a fix for an issue where it is seen that
> Deserialization of a javax.print.attribute.standard.MediaPrintableArea 
> printer attribute fails when the serialization happened in a prior 
> invocation of the program
> only for a *non-standard* page size say 4"x6"
>
> It is because EnumSyntax.readResolve() tries to get the EnumSyntax[] 
> table from Win32MediaSize when the objects are read
> and if the EnumSyntax table is not initialized or 0 in length, then 
> readResolve() will find the object value being read is not in the 
> EnumSyntax table and will throw this InvalidObjectException
>
> java.io.InvalidObjectException: Integer value = 9 not in valid range 
> 0..-1for class class sun.print.Win32MediaSize
>     at 
> javax.print.attribute.EnumSyntax.readResolve(java.desktop at 9-internal/EnumSyntax.java:204)
>     at 
> jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base at 9-internal/Native 
> Method)
>     at 
> jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base at 9-internal/NativeMethodAccessorImpl.java:62)
>     at 
> jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base at 9-internal/DelegatingMethodAccessorImpl.java:43)
>     at 
> java.lang.reflect.Method.invoke(java.base at 9-internal/Method.java:533)
>     at 
> java.io.ObjectStreamClass.invokeReadResolve(java.base at 9-internal/ObjectStreamClass.java:1150)
>     at 
> java.io.ObjectInputStream.readOrdinaryObject(java.base at 9-internal/ObjectInputStream.java:1835)
>     at 
> java.io.ObjectInputStream.readObject0(java.base at 9-internal/ObjectInputStream.java:1371)
>     at 
> java.io.ObjectInputStream.readObject(java.base at 9-internal/ObjectInputStream.java:371)
>
> When the printDialog() is invoked, then EnumSyntax table will be 
> initialised to the current paper ids. But, if printDIalog() is invoked 
> AFTER objects are deserialised, we run into this problem of enumTable 
> being 0 in length.
>
> Proposed fix is, to check if the enumtable is not initialised, then 
> fallback to the supported media size enum table.
>
> webrev: http://cr.openjdk.java.net/~psadhukhan/6278300/webrev.00/
>
> I made it noreg-hard as it needs a custom paper size to be added to 
> printer media list before invoking the serialization testcase present 
> in JBS bug entry.
>
> Regards
> Prasanta

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/2d-dev/attachments/20160725/171cd3d9/attachment.html>


More information about the 2d-dev mailing list