Skip to content

Fix stream invalidation when statement goes out of scope (GH#1443)#1598

Merged
jahnvi480 merged 7 commits intodevfrom
jahnvi/ghi_1443
Apr 8, 2026
Merged

Fix stream invalidation when statement goes out of scope (GH#1443)#1598
jahnvi480 merged 7 commits intodevfrom
jahnvi/ghi_1443

Conversation

@jahnvi480
Copy link
Copy Markdown
Contributor

This pull request addresses a critical bug where binary streams returned from a statement could become invalid if the statement object went out of scope, even though the stream was still in use. The changes ensure the statement resource remains alive as long as any associated stream is referenced, preventing premature destruction and stream invalidation. Additionally, a regression test is added to verify the fix.

Bug Fixes and Resource Management:

  • Modified sqlsrv_stream and sqlsrv_stmt structures to track and retain a reference to the statement's zend_resource, ensuring the statement is not destroyed while a stream is active.
  • Updated stream creation logic to increment the statement resource's reference count when a stream is created, and to properly release it when the stream is closed.
  • Ensured that the statement's zend_resource is stored during both sqlsrv_prepare and sqlsrv_query so streams can access it.

Testing and Documentation:

  • Added a functional test (sqlsrv_stream_outlives_stmt.phpt) to confirm that streams remain valid after their originating statement goes out of scope, covering multiple scenarios.
  • Updated the changelog to document the bug fix for binary streams becoming invalid when the statement goes out of scope.

When a stream is created from sqlsrv_get_field, the stream now holds a
reference (GC_ADDREF) to the statement's zend_resource. This prevents
PHP from destroying the statement while the stream is still alive.

Previously, if $stmt went out of scope (e.g. returned from a function),
the statement destructor would close the stream, making it invalid even
though userland code still held a reference to it.

Changes:
- Added zend_resource* stmt_res to sqlsrv_stream struct to hold a
  reference to the parent statement resource
- Added zend_resource* zend_res to sqlsrv_stmt struct so the statement
  knows its own resource handle
- On stream creation, increment statement resource refcount via GC_ADDREF
- On stream close, release the reference via zend_list_delete after
  clearing active_stream (prevents double-close in statement destructor)
- Store zend_resource on statement after registration in both
  sqlsrv_prepare and sqlsrv_query paths

Fixes: #1443
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a lifecycle bug in the SQLSRV driver where a binary stream returned from a statement could become invalid if the statement resource was destroyed while the stream was still in use, by keeping the statement’s zend_resource alive for the stream’s lifetime.

Changes:

  • Track the statement’s zend_resource on sqlsrv_stmt and retain/release it from sqlsrv_stream to prevent premature statement destruction while a stream exists.
  • Update stream close logic to drop the held statement resource reference safely.
  • Add a functional regression test covering streams that outlive their originating statement scope, and update the changelog.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/functional/sqlsrv/sqlsrv_stream_outlives_stmt.phpt Regression test ensuring streams remain readable after $stmt goes out of scope.
source/sqlsrv/conn.cpp Stores the statement’s zend_resource after resource registration for later use by streams.
source/shared/core_stream.cpp Releases the held statement resource reference when the stream is closed.
source/shared/core_stmt.cpp Adds a statement-resource retain when creating a stream from a field.
source/shared/core_sqlsrv.h Extends sqlsrv_stmt and sqlsrv_stream structs to track the statement’s zend_resource.
CHANGELOG.md Adds release note entry for the stream invalidation fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CHANGELOG.md Outdated
David-Engel
David-Engel previously approved these changes Apr 7, 2026
Comment thread test/functional/sqlsrv/sqlsrv_stream_outlives_stmt.phpt
@jahnvi480 jahnvi480 changed the base branch from jahnvi/ghi1466 to dev April 8, 2026 05:50
@jahnvi480 jahnvi480 dismissed David-Engel’s stale review April 8, 2026 05:50

The base branch was changed.

jahnvi480 and others added 3 commits April 8, 2026 11:21
Test 4: Memory leak detection - runs the stream-outlives-stmt pattern 20
times and verifies memory usage stays stable, confirming both the stream
and statement are properly freed when the stream is closed.

Test 5: Connection health - verifies the connection remains fully
functional after all streams/statements are cleaned up, proving no
dangling ODBC handles remain.
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.74%. Comparing base (add33e6) to head (68f9adf).
⚠️ Report is 1 commits behind head on dev.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##              dev    #1598      +/-   ##
==========================================
+ Coverage   85.73%   85.74%   +0.01%     
==========================================
  Files          23       23              
  Lines        7212     7221       +9     
==========================================
+ Hits         6183     6192       +9     
  Misses       1029     1029              
Files with missing lines Coverage Δ
source/shared/core_sqlsrv.h 89.68% <ø> (ø)
source/shared/core_stmt.cpp 93.51% <100.00%> (+0.01%) ⬆️
source/shared/core_stream.cpp 86.86% <100.00%> (+0.41%) ⬆️
source/sqlsrv/conn.cpp 83.37% <100.00%> (+0.09%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jahnvi480 jahnvi480 merged commit 204c4de into dev Apr 8, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants