[Bug] StreamUtils treats InputStream.available() as the remaining stream length
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 75/100
Direzione di ricerca
Inizia da skipUnusedStream e limitedInputStream in dubbo-common/src/main/java/org/apache/dubbo/common/io/StreamUtils.java; entrambi si basano su available(). Leggi la riproduzione nell'issue, che contiene due casi JUnit con un InputStream personalizzato il cui available() restituisce 0 oppure resta indietro rispetto a skip(). È fatto quando entrambi i casi passano: i cicli di svuotamento avanzano con read()/skip() fino a EOF e il limite non viene ricavato da available().
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Pre-check
- I am sure that all the content I provide is in English.
Search before asking
- I had searched in the issues and found no similar issues.
Apache Dubbo Component
Java SDK (apache/dubbo)
Dubbo Version
Apache Dubbo source: 3.3.7-SNAPSHOT, branch 3.3, commit ae809de2fc81b408194240965eb20bf27e6971df.
Windows 11, OpenJDK 21, Maven 3.6.3.
Two focused utility regressions were run in an isolated Maven/JUnit harness using byte-for-byte source copies. No registry or network service is required.
Steps to reproduce this issue
Component
Java SDK (apache/dubbo), dubbo-common.
Summary
StreamUtils.skipUnusedStream(InputStream) uses InputStream.available() to decide whether to skip data, and performs only one skip call. This is incorrect for general InputStream implementations: available() may legally return zero even when a read would produce data, and skip(n) may skip fewer than n bytes. The method can leave request/serialization bytes unread.
The same available() assumption also appears in limitedInputStream, which sets its limit to Math.min(limit, is.available()); a stream with data but available() == 0 is exposed as immediately exhausted.
Version and verification scope
- Apache Dubbo
3.3.7-SNAPSHOT, branch3.3, commitae809de2fc81b408194240965eb20bf27e6971df. - Windows 11, OpenJDK 21, Maven 3.6.3.
- Two implementation files were copied byte-for-byte from the commit into an isolated Maven/JUnit harness. No network service or registry is required.
- This is a focused utility regression, not a full reactor build or production protocol validation.
Reproduction
static class AvailableZeroStream extends InputStream {
private final byte[] data = "payload".getBytes();
private int index;
public int available() { return 0; }
public int read() { return index < data.length ? data[index++] & 0xff : -1; }
public long skip(long n) {
long amount = Math.min(n, Math.max(0, data.length - index));
index += (int) amount;
return amount;
}
}
@Test
void skipUnusedStreamMustDrainStreamsWhoseAvailableIsZero() throws Exception {
AvailableZeroStream in = new AvailableZeroStream();
StreamUtils.skipUnusedStream(in);
assertEquals(-1, in.read()); // fails: returns 'p'
}
@Test
void skipUnusedStreamMustContinueWhenSkipReturnsLessThanAvailable() throws Exception {
InputStream in = new InputStream() {
private int remaining = 5;
public int available() { return remaining; }
public int read() { if (remaining == 0) return -1; remaining--; return 'x'; }
public long skip(long n) { long skipped = Math.min(1, n); remaining -= skipped; return skipped; }
};
StreamUtils.skipUnusedStream(in);
assertEquals(-1, in.read()); // fails: returns 'x'
}
Executed result: both assertions failed; the normal JUnit control for Ring passed. The failure is caused by the actual upstream StreamUtils class.
Expected behavior
A utility that drains or limits an input stream should use read()/skip() progress until EOF or the requested limit is reached. available() is only an estimate of non-blocking bytes and must not be used as the stream's total length. If the intended contract is only “skip currently available bytes”, the method name and documentation should state that explicitly and the one-shot skip should still handle partial progress.
Root cause
skipUnusedStream guards the only skip call with is.available() > 0. limitedInputStream similarly uses is.available() as its initial limit. Both paths break for standard custom/network/decompressing streams where available() is zero or smaller than the remaining data.
Deduplication
Searched open issues for StreamUtils, available skip, skipUnusedStream, and stream payload handling. I did not find a report of this root cause in the searched results. This is separate from the existing Bytes/InputStream MD5 report #16451.
What you expected to happen
Stream utility methods should not use InputStream.available() as the total remaining length. A valid stream with available()==0 must not be treated as empty, and a partial skip must be retried until the intended data is consumed.
Both focused regressions failed against the unchanged upstream implementation.
Anything else
Root cause: skipUnusedStream checks available()>0 and performs one skip call; limitedInputStream also derives its limit from available(). InputStream.available() is only a non-blocking estimate and skip() may return fewer bytes than requested.
Searched open issues for StreamUtils, available skip, skipUnusedStream and stream payload handling; no matching root-cause report was found. This is separate from the existing Bytes/InputStream MD5 report #16451.
Do you have a (mini) reproduction demo?
- Yes, I have a minimal reproduction demo to help resolve this issue more effectively!
Are you willing to submit a pull request to fix on your own?
- Yes I am willing to submit a pull request on my own!
Code of Conduct
- I agree to follow this project's Code of Conduct
- Lingua principale
- Java
- Stelle
- 41.6k
- Fork
- 26.3k
- Merge medio
- 1g 22h
- PR unite (30g)
- 19
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di apache/dubbo
-
[Bug] Auto-trusted serialization allow list skips array component classesForse già presa @Icesource l’ha presa 4 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
apache/dubbo#16569 · 1 commento · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug] QoS count command ignores the times argument after cdForse già presa @CCCLL l’ha presa 19 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
apache/dubbo#16530 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug] AccessLogFilter accesslog path warnings are garbled and name the wrong accesslog.fixed.path valueForse già presa @CCCLL l’ha presa 19 giorni fa. Aperta
Difficoltà 1/5 1-3 ore Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
-
[Bug] dubbo.protocol.triple.max-message-size is only read from OS environment variablesForse già presa @CCCLL l’ha presa 20 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
[Bug] Negative frame data length causes IllegalArgumentException in ExchangeCodecForse già presa @L1nq0 l’ha presa 64 giorni fa. Apertacomponent/need-triage type/need-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di apache/dubbo
Issue simili
-
Document and enforce pull request review guidelinesForse già presa @dashorst l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
`Time.at(t, in: nil)` returns UTC instead of the local time (or the time zone of `t`), unlike CRubyAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
hermes-queue
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 72/100
chrisalunlloyd2-sudo/mindpalace#349 ·
I maintainer di solito rispondono entro 1 giorno
-
Retry-After parser accepts invalid delay-seconds valuesForse già presa @Dhruvraj-Rana l’ha presa oggi. ApertaBug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
open-telemetry/opentelemetry-java#9018 ·
I maintainer di solito rispondono entro 2 giorni
-
dropwizard-testing: DAOTest.inTransaction leaves the transaction open when an Error is thrownAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
dropwizard/dropwizard#11410 ·
I maintainer di solito rispondono entro 1 giorno