Skip to content

FIX: prevent native log format-string injection - #791

Merged
Gaurav Sharma (bewithgaurav) merged 5 commits into
mainfrom
sumitsar/fix-vfind-149-format-string
Sep 22, 2026
Merged

Gaurav Sharma (bewithgaurav) merged 5 commits into
mainfrom
sumitsar/fix-vfind-149-format-string

Conversation

@sumitmsft

@sumitmsft Sumit Sarabhai (sumitmsft) commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Work Item / Issue Reference

AB#48241


Summary

Prevents server-controlled Arrow column metadata from being interpreted as a native printf-style format string.

Converts all dynamic native LOG calls to literal formats, fixes existing format/argument mismatches exposed by compiler checking, and enables compile-time printf validation for GCC, Clang, and AppleClang.

Adds a source-contract regression test that rejects nonliteral native LOG formats across first-party C++ sources and headers.

Validation

  • Windows x64 native extension build completed with 0 errors.
  • 37 no-database dependency and logging-security tests passed; 3 platform-specific tests skipped.
  • Rebuilt package import passed.
  • Python formatting and diff checks passed.
  • Independent rubber-duck review completed with no remaining findings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 17, 2026 08:31
@github-actions github-actions Bot added the pr-size: medium Moderate update size label Sep 17, 2026
Comment thread mssql_python/pybind/logger_bridge.hpp Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No unresolved blocking issues were identified.

Pull request overview

Prevents native printf-style log injection from server-controlled metadata and adds compile-time validation.

Changes:

  • Converts dynamic log calls to literal formats.
  • Fixes format mismatches.
  • Adds compiler checks and regression tests.
File summaries
File Description
tests/test_039_native_logging_format_security.py Adds logging format-security regression tests.
mssql_python/pybind/logger_bridge.hpp Adds printf-format annotations.
mssql_python/pybind/ddbc_bindings.cpp Secures and corrects native log calls.
mssql_python/pybind/CMakeLists.txt Enables format diagnostics.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

📊 Code Coverage Report

🔥 Diff Coverage

50%


🎯 Overall Coverage

84%


📈 Total Lines Covered: 8813 out of 10455
📁 Project: mssql-python


Diff Coverage

Diff: main...HEAD, staged and unstaged changes

  • mssql_python/pybind/ddbc_bindings.cpp (50.0%): Missing lines 2734,2736,2763-2764

Summary

  • Total: 8 lines
  • Missing: 4 lines
  • Coverage: 50%

mssql_python/pybind/ddbc_bindings.cpp

Lines 2730-2740

  2730                             py::bytes b = element.cast<py::bytes>();
  2731                             if (PyBytes_GET_SIZE(b.ptr()) != 16) {
  2732                                 LOG("BindParameterArray: GUID bytes wrong "
  2733                                     "length - param_index=%d, row=%zu, "
! 2734                                     "length=%lld",
  2735                                     paramIndex, i,
! 2736                                     static_cast<long long>(PyBytes_GET_SIZE(b.ptr())));
  2737                                 ThrowStdException("UUID binary data must be "
  2738                                                   "exactly 16 bytes long.");
  2739                             }
  2740                             std::memcpy(uuid_bytes.data(), PyBytes_AS_STRING(b.ptr()), 16);

Lines 2759-2768

  2759                         std::memcpy(guidArray[i].Data4, uuid_bytes.data() + 8, 8);
  2760                         strLenOrIndArray[i] = sizeof(SQLGUID);
  2761                     }
  2762                     LOG("BindParameterArray: SQL_C_GUID bound - "
! 2763                         "param_index=%d, count=%zu",
! 2764                         paramIndex, paramSetSize);
  2765                     dataPtr = guidArray;
  2766                     bufferLength = sizeof(SQLGUID);
  2767                     break;
  2768                 }


📋 Files Needing Attention

📉 Files with overall lowest coverage (click to expand)
mssql_python.pybind.performance_counter.hpp: 0.7%
mssql_python.pybind.logger_bridge.cpp: 57.9%
mssql_python.pybind.ddbc_bindings.h: 64.1%
mssql_python.pybind.logger_bridge.hpp: 70.8%
mssql_python.pybind.ddbc_bindings.cpp: 78.4%
mssql_python.pybind.connection.connection_pool.cpp: 82.3%
mssql_python.pybind.connection.connection.cpp: 82.5%
mssql_python.logging.py: 86.2%
mssql_python.pooling.py: 90.1%
mssql_python.pybind.fetch_temporal.hpp: 92.1%

🔗 Quick Links

⚙️ Build Summary 📋 Coverage Details

View Azure DevOps Build

Browse Full Coverage Report

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 17, 2026 10:21
@sumitmsft
Sumit Sarabhai (sumitmsft) marked this pull request as ready for review September 17, 2026 10:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note

Copilot was unable to run its full agentic suite in this review.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings September 18, 2026 10:30
@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

PR Performance Report

No consistent slowdowns detected across all 2 environments.

Coverage: 2 of 2 environments completed. Advisory result; does not block merging.

Environment Status
Unix / SQL Server 2022 Completed
Unix / SQL Server 2025 Completed
Affected phases and call counts

Phase times are inclusive diagnostics and must not be added together. They identify where measured time changed, not why it changed.

No affected phases or call-count changes were recorded.

All database tasks and timings

Unix / SQL Server 2022

Database task Before After Paired change Result
Connection opening 10.602 ms 10.552 ms -0.4% no signal
SELECT queries 1.169 ms 1.149 ms -1.6% no signal
Row insertion 34.774 ms 34.744 ms -1.3% no signal
Executemany inserts 166.165 ms 158.629 ms -0.1% no signal
Fetch-all queries 143.869 ms 141.136 ms -2.3% no signal
Row-by-row fetching 56.799 ms 56.817 ms +0.6% no signal
Batched row fetching 143.254 ms 145.367 ms +0.3% no signal
Transaction commit and rollback 114.559 ms 115.221 ms +1.6% no signal
Arrow row fetching 92.837 ms 97.503 ms +4.4% no signal
100,000-row insertion 443.650 ms 439.506 ms -0.8% no signal
Row fetching in batches of 100 195.070 ms 195.950 ms +1.1% no signal
Row fetching in batches of 10,000 160.615 ms 161.329 ms +9.2% no signal
Repeated positional queries 44.237 ms 42.254 ms -6.0% no signal
Repeated named-parameter queries 44.716 ms 43.946 ms -0.8% no signal
Legacy 100,000-row insertion 349.499 ms 350.521 ms +0.1% no signal
Insertion with explicit input sizes 499.967 ms 531.278 ms +6.3% no signal
Joined aggregation queries 181.281 ms 180.693 ms -1.6% no signal
Large joined-result fetching 198.923 ms 197.572 ms +0.5% no signal
1.2-million-row fetching 3480.375 ms 3546.410 ms +2.2% no signal
Common table expression queries 5.281 ms 5.376 ms +1.9% no signal

Unix / SQL Server 2025

Database task Before After Paired change Result
Connection opening 96.807 ms 95.949 ms -1.0% no signal
SELECT queries 1.197 ms 1.089 ms -8.7% no signal
Row insertion 31.804 ms 31.990 ms +0.6% no signal
Executemany inserts 130.699 ms 131.949 ms +2.1% no signal
Fetch-all queries 137.175 ms 139.401 ms +1.6% no signal
Row-by-row fetching 49.514 ms 49.894 ms -0.0% no signal
Batched row fetching 135.475 ms 134.537 ms -0.6% no signal
Transaction commit and rollback 103.530 ms 103.709 ms -0.3% no signal
Arrow row fetching 88.550 ms 90.071 ms -1.0% no signal
100,000-row insertion 401.979 ms 396.423 ms -2.4% no signal
Row fetching in batches of 100 176.496 ms 175.363 ms -0.5% no signal
Row fetching in batches of 10,000 154.862 ms 157.027 ms +1.4% no signal
Repeated positional queries 38.210 ms 38.334 ms +0.3% no signal
Repeated named-parameter queries 40.428 ms 40.489 ms +0.4% no signal
Legacy 100,000-row insertion 311.646 ms 311.280 ms -0.1% no signal
Insertion with explicit input sizes 437.884 ms 440.706 ms +0.6% no signal
Joined aggregation queries 165.947 ms 166.123 ms -0.7% no signal
Large joined-result fetching 193.334 ms 191.033 ms -1.0% no signal
1.2-million-row fetching 3506.065 ms 3527.548 ms +0.6% no signal
Common table expression queries 5.274 ms 5.236 ms -0.1% no signal
Build, commits and measurement details

ADO build 177139

PR head: ddadd5d96eb0a1ebca089952ee57d50de2faf29c
Base: a5faa3289a4cec65495bc51bfdb1135c8e70d97f
Measured merge: 8dcd26a2deffe7886b4c54e03f169e9a92f3c922

  • Unix / SQL Server 2022: Python 3.12.3, x86_64, SQL 16.0.4295.3; 5 paired comparisons and 1 warmup.
  • Unix / SQL Server 2025: Python 3.12.3, x86_64, SQL 17.0.5005.3; 5 paired comparisons and 1 warmup.

A consistent change requires more than 20% median paired movement, at least 1 ms between the median runtimes, and at least 80% of pairs exceeding the relative threshold in the same direction. A slowdown without enough pair agreement is reported as inconsistent.

The displayed change is the median of paired before-and-after ratios. It is not recalculated from the two displayed median runtimes.

Both revisions use profiling-enabled builds on the same agent and database, with alternating order and discarded warmups. Results are diagnostic and do not represent production-wheel latency.

Raw samples and logs are attached to the ADO run as profiler-* artifacts.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this addresses the reported format-string issue and keeps the existing error behavior intact. one optional suggestion to strengthen regression coverage. approving.

Comment thread tests/test_039_native_logging_format_security.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The source-contract test can miss multiline dynamic log format expressions.

Review details

Suppressed comments (1)

tests/test_039_native_logging_format_security.py:32

  • This regex does not match a call whose format expression starts on the next line, because . does not match newlines by default. For example, LOG_ERROR(\n dynamic_format, ...) is skipped, so the new source-contract test can pass while a dynamic native format remains. Match the first non-whitespace character across lines (or enable DOTALL) so multiline calls are checked too.
    pattern = re.compile(r"\bLOG(?:_INFO|_WARNING|_ERROR)?\s*\(\s*(.)")
  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 22, 2026 08:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Update the regression test to cover multiline native logging calls.

Review effort: Lite
Findings: None

Copilot AI review requested due to automatic review settings September 22, 2026 10:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

No unresolved blocking issues remain.

Review effort: Lite
Findings: None

@bewithgaurav
Gaurav Sharma (bewithgaurav) merged commit 171d130 into main Sep 22, 2026
32 of 34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-size: medium Moderate update size

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants