Skip to content

Commit fbcc650

Browse files
Fix IOBuffer leak in Do_upstream_rsp_body
1 parent 92941b9 commit fbcc650

1 file changed

Lines changed: 22 additions & 13 deletions

File tree

plugin/src/Machinery.cc

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,8 +2512,19 @@ const HookMask Do_upstream_rsp_body::HOOKS{MaskFor({Hook::URSP})};
25122512
Errata
25132513
Do_upstream_rsp_body::invoke(Context &ctx)
25142514
{
2515+
// State allocated in transaction memory.
2516+
struct State {
2517+
TextView _view; ///< Source view for body.
2518+
TSIOBuffer _tsio_buff = nullptr; ///< Buffer used to write body.
2519+
};
2520+
25152521
auto static transform = [](TSCont contp, TSEvent ev_code, void *) -> int {
2516-
if (TSVConnClosedGet(contp)) {
2522+
2523+
if (TSVConnClosedGet(contp)) { // all done, time to clean up.
2524+
auto state = static_cast<State*>(TSContDataGet(contp));
2525+
if (state && state->_tsio_buff) {
2526+
TSIOBufferDestroy(state->_tsio_buff);
2527+
}
25172528
TSContDestroy(contp);
25182529
return 0;
25192530
}
@@ -2539,14 +2550,12 @@ Do_upstream_rsp_body::invoke(Context &ctx)
25392550
TSContCall(TSVIOContGet(in_vio),
25402551
(TSVIONTodoGet(in_vio) <= 0) ? TS_EVENT_VCONN_WRITE_COMPLETE : TS_EVENT_VCONN_WRITE_READY, in_vio);
25412552
}
2542-
// If the full is there, create the output buffer and write it, then clear it.
2543-
auto view = static_cast<TextView *>(TSContDataGet(contp));
2544-
if (view) {
2553+
// If the buffer isn't already there, create it and write out the view.
2554+
if ( auto state = static_cast<State *>(TSContDataGet(contp)) ; state && ! state->_tsio_buff) {
25452555
auto out_vconn = TSTransformOutputVConnGet(contp);
2546-
auto out_buff = TSIOBufferCreate();
2547-
auto out_vio = TSVConnWrite(out_vconn, contp, TSIOBufferReaderAlloc(out_buff), view->size());
2548-
TSIOBufferWrite(out_buff, view->data(), view->size());
2549-
TSContDataSet(contp, nullptr);
2556+
state->_tsio_buff = TSIOBufferCreate();
2557+
TSIOBufferWrite(state->_tsio_buff, state->_view.data(), state->_view.size());
2558+
auto out_vio = TSVConnWrite(out_vconn, contp, TSIOBufferReaderAlloc(state->_tsio_buff), state->_view.size());
25502559
TSVIOReenable(out_vio);
25512560
}
25522561
}
@@ -2575,12 +2584,12 @@ Do_upstream_rsp_body::invoke(Context &ctx)
25752584
}
25762585

25772586
if (content) {
2578-
// The view contents are in the transaction data, but the full in the feature is not.
2579-
// Make a copy there and pass its address to the continuation.
2580-
auto ctx_view = ctx.alloc_span<TextView>(1);
2587+
// The view contents are in the transaction data, but the view in the feature is not.
2588+
// Put a copy in the transform @a state.
2589+
auto state = ctx.make<State>();
25812590
auto cont = TSTransformCreate(transform, ctx._txn);
2582-
ctx_view[0] = *content;
2583-
TSContDataSet(cont, ctx_view.data());
2591+
state->_view = *content;
2592+
TSContDataSet(cont, state);
25842593
TSHttpTxnHookAdd(ctx._txn, TS_HTTP_RESPONSE_TRANSFORM_HOOK, cont);
25852594
ctx._txn.ursp_hdr().field_obtain("Content-Type"_tv).assign(content_type);
25862595
}

0 commit comments

Comments
 (0)