[ 
https://issues.apache.org/jira/browse/HDDS-15480?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated HDDS-15480:
----------------------------------
    Labels: pull-request-available  (was: )

> Potential for NPE / infinite loop in StreamBlockReader
> ------------------------------------------------------
>
>                 Key: HDDS-15480
>                 URL: https://issues.apache.org/jira/browse/HDDS-15480
>             Project: Apache Ozone
>          Issue Type: Sub-task
>            Reporter: Stephen O'Donnell
>            Assignee: Stephen O'Donnell
>            Priority: Major
>              Labels: pull-request-available
>
> There is potential for an NPE at stream shutdown in the StreamBlockReader:
> poll() explicitly returns null when future.isDone() is true (stream 
> completed). However readFromQueue() uses the return value without a null 
> check:
> {code}
>   // StreamingReader.readFromQueue(), line 455-459
>   ByteBuffer readFromQueue() throws IOException {
>       final ReadBlockResponseProto readBlock = poll();   // can return null
>       final ByteString data = readBlock.getData();       // NPE!
> {code}
> This fires in the normal shutdown path: after the server sends the last chunk 
> and closes the stream, the next poll() call returns null and this line throws 
> NullPointerException instead of letting the caller handle EOF gracefully.
> Fixing this, can then cause an infinite loop in StreamingReader.read() (lines 
> 446-451)
>   
> The inner read loop has no exit when readFromQueue() returns null or an empty 
> buffer:
> {code}
>   while (true) {
>       final ByteBuffer buf = readFromQueue();
>       if (buf != null && buf.hasRemaining()) {
>           return buf;     // only exit
>       }
>       // else: loop forever
>   }
> {code}
> This could happen when:
>   - Stream ends: once Bug 1 is fixed so readFromQueue() can return null, this 
> loop spins forever on null.
>   - Full offset skip: readFromQueue() adjusts the buffer position by pos - 
> blockOffset. If the entire response arrived before the current position (e.g. 
> after a seek, or when reading near the end of a small block), the adjusted 
> buffer has 0 remaining bytes. The loop spins indefinitely without requesting 
> new data, because readBlock() is only called once before the loop starts.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to