summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/couchdb/couch_db.erl20
1 files changed, 16 insertions, 4 deletions
diff --git a/src/couchdb/couch_db.erl b/src/couchdb/couch_db.erl
index 95a68311..82231924 100644
--- a/src/couchdb/couch_db.erl
+++ b/src/couchdb/couch_db.erl
@@ -644,12 +644,24 @@ write_streamed_attachment(_Stream, _F, 0, SpAcc) ->
{ok, SpAcc};
write_streamed_attachment(Stream, F, LenLeft, nil) ->
Bin = F(),
- {ok, StreamPointer} = couch_stream:write(Stream, Bin),
- write_streamed_attachment(Stream, F, LenLeft - size(Bin), StreamPointer);
+ TruncatedBin = check_bin_length(LenLeft, Bin),
+ {ok, SpAcc} = couch_stream:write(Stream, TruncatedBin),
+ write_streamed_attachment(Stream, F, LenLeft - size(TruncatedBin), SpAcc);
write_streamed_attachment(Stream, F, LenLeft, SpAcc) ->
Bin = F(),
- {ok, _} = couch_stream:write(Stream, Bin),
- write_streamed_attachment(Stream, F, LenLeft - size(Bin), SpAcc).
+ TruncatedBin = check_bin_length(LenLeft, Bin),
+ {ok, _} = couch_stream:write(Stream, TruncatedBin),
+ write_streamed_attachment(Stream, F, LenLeft - size(TruncatedBin), SpAcc).
+
+%% on rare occasions ibrowse seems to process a chunked response incorrectly
+%% and include an extra "\r" in the last chunk. This code ensures that we
+%% truncate the downloaed attachment at the length specified in the metadata.
+check_bin_length(LenLeft, Bin) when size(Bin) > LenLeft ->
+ <<ValidData:LenLeft/binary, Crap/binary>> = Bin,
+ ?LOG_ERROR("write_streamed_attachment has written too much expected: ~p" ++
+ " got: ~p tail: ~p", [LenLeft, size(Bin), Crap]),
+ ValidData;
+check_bin_length(_, Bin) -> Bin.
enum_docs_since_reduce_to_count(Reds) ->
couch_btree:final_reduce(