This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git
The following commit(s) were added to refs/heads/main by this push:
new e89219848 Fix multipart parser "attachment longer than expected" error
e89219848 is described below
commit e892198483abbe0cab39d71bd2201a40f05be07b
Author: Nick Vatamaniuc <[email protected]>
AuthorDate: Mon Jul 17 16:42:56 2023 -0400
Fix multipart parser "attachment longer than expected" error
Previously, we used a stale `Waiting` list of workers instead of the updated
`NewWaiting` one. Then, when we recursed back to the top in
`maybe_send_data/1`, and tried to reply to all waiting clients, we re-sent
the
same block to the client. That client would then get more attachment blocks
than it expected and would throw an `attachment longer than expected` error.
At the API level this would manifest as an intermittent 400 (bad_request)
HTTP
error for multipart document + attachments PUTs. For the error to occur, a
`{hello_from_writer, ...}` has to be recieved when we're in the bottom part
of
`maybe_send_data/1` in the couch_httpd_multipart parser. However, due to how
CouchDB replicator skips over documents PUTs which generate 4xx errors, the
effect was that these documents were skipped over during replication, with
only
a `doc_write_failures` statistic bump to indicate that something went wrong.
There is a somewhat related issue for discussion whether that replicator
behavior is desirable [1]
[1] https://github.com/apache/couchdb/issues/4676.
---
src/couch/src/couch_httpd_multipart.erl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/couch/src/couch_httpd_multipart.erl
b/src/couch/src/couch_httpd_multipart.erl
index 11ee6790e..80fc48a75 100644
--- a/src/couch/src/couch_httpd_multipart.erl
+++ b/src/couch/src/couch_httpd_multipart.erl
@@ -203,7 +203,7 @@ maybe_send_data({Ref, Chunks, Offset, Counters, Waiting}) ->
end;
{hello_from_writer, Ref, WriterPid} ->
C2 = handle_hello(WriterPid, Counters),
- maybe_send_data({Ref, NewChunks, NewOffset, C2,
Waiting});
+ maybe_send_data({Ref, NewChunks, NewOffset, C2,
NewWaiting});
{get_bytes, Ref, X} ->
C2 = update_writer(X, Counters),
maybe_send_data({Ref, NewChunks, NewOffset, C2, [X |
NewWaiting]})