On Fri, 5 Mar 2021 01:27:47 GMT, Sergey Bylokhov <s...@openjdk.org> wrote:

>> **Root cause:**
>> `getPrinterNames()` has two calls to 
>> [`::EnumPrinters`](https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinters).
>>  The first call is to get the required buffer size to contain the structures 
>> and any strings. The second call is to get the list of printers.
>> 
>> Yet the list of printers or the names of printers can change between the two 
>> calls. If it happens, the second call to `EnumPrinters` fails but it is not 
>> checked.
>> 
>> I couldn't reproduce the crash myself. However, I reproduced the failure in 
>> the second call to `::EnumPrinters` by adding `::Sleep(500)` and by renaming 
>> the printers so that the data doesn't fit into the allocated buffer:
>> 
>> 1: bResult: 0, cbNeeded: 504, cReturned: 0
>> 2: bResult: 0, cbNeeded: 512, cReturned: 0
>>     !!! error
>> 
>> During my testing, `cReturned` has always been zero whenever `EnumPrinters` 
>> fails.
>> 
>> The crash dumps show that `cReturned` is non-zero but the `pPrinterEnum` 
>> buffer doesn't contain valid data. Reading `info4->pPrinterName` at the line
>> utf_str = JNU_NewStringPlatform(env, info4->pPrinterName);
>> raises Access Violation exception.
>> 
>> **The fix:**
>> Check the return value of `EnumPrinters` and allow for 5 retries. If the 
>> function still returns failure, make sure `cReturned` is set to zero.
>> 
>> I'm going to close 
>> [JDK-6996051](https://bugs.openjdk.java.net/browse/JDK-6996051) and 
>> [JDK-8182683](https://bugs.openjdk.java.net/browse/JDK-8182683) reported 
>> previously about the same crash as duplicate of the current 
>> [JDK-8262829](https://bugs.openjdk.java.net/browse/JDK-8262829).
>> 
>> **Testing:**
>> I used 
>> [`RemotePrinterStatusRefresh.java`](https://github.com/openjdk/jdk/blob/master/test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java)
>>  for testing, it shows the list of currently available printers. In the 
>> background I ran `PrinterRename.ps1` PowerShell script which remains a 
>> printer, the script is attached to the JBS issue.
>> 
>> Without the fix, the list of available printers was empty occasionally 
>> because `EnumPrinters` returned failure and set `cReturned` to zero. With 
>> the fix, the list of printers is always filled.
>
> src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp line 136:
> 
>> 134: 
>> 135:     try {
>> 136:         ::EnumPrinters(flags, NULL, 4, NULL,
> 
> Don't we need to check that this method call succeeds? Probably it is a crash 
> reason when the EnumPrinters fails but we use cbNeeded anyway for array 
> allocation?

I guess since we are changing this method anyway, can we use 
PRINTER_ENUM_CONNECTIONS flag instead of hardcoded 4 so that it is more 
informative!!

-------------

PR: https://git.openjdk.java.net/jdk/pull/2836

Reply via email to