[prev in list] [next in list] [prev in thread] [next in thread]
List: openjdk-2d-dev
Subject: Re: [OpenJDK 2D-Dev] [9] RFR JDK-6278300: sun.print.Win32MediaSize deserialization error
From: Phil Race <philip.race () oracle ! com>
Date: 2016-07-25 20:24:06
Message-ID: 57967566.2060604 () oracle ! com
[Download RAW message or body]
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@9-internal/EnumSyntax.java:204)
> at
> jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-internal/Native
> Method)
> at
> jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-internal/NativeMethodAccessorImpl.java:62)
> at
> jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-internal/DelegatingMethodAccessorImpl.java:43)
> at
> java.lang.reflect.Method.invoke(java.base@9-internal/Method.java:533)
> at
> java.io.ObjectStreamClass.invokeReadResolve(java.base@9-internal/ObjectStreamClass.java:1150)
> at
> java.io.ObjectInputStream.readOrdinaryObject(java.base@9-internal/ObjectInputStream.java:1835)
> at
> java.io.ObjectInputStream.readObject0(java.base@9-internal/ObjectInputStream.java:1371)
> at
> java.io.ObjectInputStream.readObject(java.base@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
[Attachment #3 (text/html)]
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">The fix seems wrong to me .. and the
problem is not easy.<br>
<br>
Windows defines standard paper sizes and we recognise those and
will always serialise<br>
the "Media" as one of the built-in java pre-defined Media.<br>
<br>
But windows printer drivers very typically define additional
driver-specific papers,<br>
so at runtime JDK dynamically creates new instances as these are
discovered.<br>
<br>
They will be instances of Win32MediaSize and their IDs (enum int
values) will<br>
be entirely dependent on the order they "happened" to be added to
the list.<br>
<br>
When you serialise this out, all you serialise is<br>
(a) the type (Win32MediaSize) and (b) the int value (see the
serialized form docs<br>
for EnumSyntax).<br>
<br>
When you come to *deserialize* then what happens depends on
whether the<br>
code that adds those to the list has been run (or not). If it has,
you may well<br>
be lucky and get the right intended paper.<br>
<br>
If it has not - which is inevitable if you load the preferences in
main(..)<br>
before any printing code has run - then the code that initialises
the table<br>
has not been run and the int value is meaningless. Pointing it to
the ID<br>
in the super-class is wrong. Also you have not run the
Win32MediaSize<br>
constructor ! So you will have deserialized a garbage instance ..
it<br>
will have an ID that does not correspond to the table, and was
meant<br>
to ID some standard paper size. So the fix is probably worse than
the bug.<br>
<br>
It seems like there should be a readResolve() for Win32MediaSize
that<br>
first initialises the table.<br>
<br>
And it is only *this simple* (yes, I mean that) because you only
have one<br>
printer involved. Get 4 printers with custom IDs and you don't
even know<br>
in which order these printers had their IDs initialised.<br>
<br>
The documented serialised form leaves you with essentially
insufficient information.<br>
It seems like Win32MediaSize needs a serialised form that includes
the extra info.<br>
But if you "delete" the printer and run the app you now have
useless serialised data<br>
and need to esstablish a policy around that.<br>
<br>
Also it seems likely we have the same issue in the CUPS code ..<br>
<br>
This is a non-trivial bug and will likely take a lot of careful
work to<br>
figure out all the spec/compat/behavioural issues.<br>
<br>
<br>
-phil.<br>
<br>
<br>
<br>
<br>
<br>
On 07/15/2016 02:36 AM, Prasanta Sadhukhan wrote:<br>
</div>
<blockquote cite="mid:5788AEB1.9010709@oracle.com" type="cite">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
Hi All,<br>
<br>
Bug: <a moz-do-not-send="true" class="moz-txt-link-freetext"
href="https://bugs.openjdk.java.net/browse/JDK-6278300">https://bugs.openjdk.java.net/browse/JDK-6278300</a><br>
<br>
Please review a fix for an issue where it is seen that<br>
Deserialization of a
javax.print.attribute.standard.MediaPrintableArea printer
attribute fails when the serialization happened in a prior
invocation of the program<br>
only for a <b>non-standard</b> page size say 4"x6"<br>
<br>
It is because EnumSyntax.readResolve() tries to get the
EnumSyntax[] table from Win32MediaSize when the objects are read <br>
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<br>
<br>
java.io.InvalidObjectException: Integer value = 9 not in valid
range 0..-1for class class sun.print.Win32MediaSize<br>
at
javax.print.attribute.EnumSyntax.readResolve(<a
moz-do-not-send="true" class="moz-txt-link-abbreviated"
href="mailto:java.desktop@9-internal/EnumSyntax.java:204">java.desktop@9-internal/EnumSyntax.java:204</a>)<br>
at
jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-internal/Native
Method)<br>
at
jdk.internal.reflect.NativeMethodAccessorImpl.invoke(<a
moz-do-not-send="true" class="moz-txt-link-abbreviated"
href="mailto:java.base@9-internal/NativeMethodAccessorImpl.java:62">java.base@9-internal/NativeMethodAccessorImpl.java:62</a>)<br>
at
jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(<a
moz-do-not-send="true" class="moz-txt-link-abbreviated"
href="mailto:java.base@9-internal/DelegatingMethodAccessorImpl.java:43">java.base@9-internal/DelegatingMethodAccessorImpl.java:43</a>)<br>
at java.lang.reflect.Method.invoke(<a moz-do-not-send="true"
class="moz-txt-link-abbreviated"
href="mailto:java.base@9-internal/Method.java:533">java.base@9-internal/Method.java:533</a>)<br>
at
java.io.ObjectStreamClass.invokeReadResolve(<a
moz-do-not-send="true" class="moz-txt-link-abbreviated"
href="mailto:java.base@9-internal/ObjectStreamClass.java:1150">java.base@9-internal/ObjectStreamClass.java:1150</a>)<br>
at
java.io.ObjectInputStream.readOrdinaryObject(<a
moz-do-not-send="true" class="moz-txt-link-abbreviated"
href="mailto:java.base@9-internal/ObjectInputStream.java:1835">java.base@9-internal/ObjectInputStream.java:1835</a>)<br>
at
java.io.ObjectInputStream.readObject0(<a moz-do-not-send="true"
class="moz-txt-link-abbreviated"
href="mailto:java.base@9-internal/ObjectInputStream.java:1371">java.base@9-internal/ObjectInputStream.java:1371</a>)<br>
at
java.io.ObjectInputStream.readObject(<a moz-do-not-send="true"
class="moz-txt-link-abbreviated"
href="mailto:java.base@9-internal/ObjectInputStream.java:371">java.base@9-internal/ObjectInputStream.java:371</a>)<br>
<br>
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.<br>
<br>
Proposed fix is, to check if the enumtable is not initialised,
then fallback to the supported media size enum table.<br>
<br>
webrev: <a moz-do-not-send="true" class="moz-txt-link-freetext"
href="http://cr.openjdk.java.net/%7Epsadhukhan/6278300/webrev.00/">http://cr.openjdk.java.net/~psadhukhan/6278300/webrev.00/</a><br>
<br>
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.<br>
<br>
Regards<br>
Prasanta<br>
</blockquote>
<br>
</body>
</html>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic