Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Merge changes from internal repo - 2026-08-14 - #319

Merged
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6
Aug 14, 2026
Merged

Merge changes from internal repo - 2026-08-14#319
linjun-he-sap merged 13 commits into
masterfrom
mirroring/2.29.6

Conversation

@linjun-he-sap

Copy link
Copy Markdown
Contributor

No description provided.

linjun-he-sapand others added 13 commits July 7, 2026 13:53
- add `diff: 8.0.4` to overrides in package.json; pulls in the patched
diff release in place of the 7.0.0 version that mocha 11.7.6 transitively
requests via `^7.0.0`
- regenerate package-lock.json via `npm install`; `npm audit` now reports 0 vulnerabilities
- vulnerability: GHSA-73rr-hh4g-fpgx ("jsdiff has a Denial of Service vulnerability in parsePatch
and applyPatch"). diff versions >=6.0.0 <8.0.3 enter an infinite loop / O(n^3) ReDoS when parsing
patches whose filename or patch headers contain `\r`, `
`, or `
`, exhausting memory or CPU. Fixed
upstream in diff 8.0.3; pinned here to the latest 8.x patch (8.0.4)
- affected dependency: diff is a dev-only transitive dependency pulled in exclusively by mocha (used
for pretty-printing assertion diffs in failing test output). it is not shipped to consumers of `hdb`
and not reachable with attacker-controlled input in our test setup, so real-world exposure is minimal
-- the override silences the npm audit alert and aligns with our existing pattern of pinning patched
majors via `overrides` (see safer-buffer, serialize-javascript)
- mocha 11.7.6 (latest stable) still declares `diff: ^7.0.0`; the fix has only landed in mocha 12 betas,
which we do not adopt. The override is the appropriate stable path until a fixed mocha stable releases
- change readable handler to loop read() until null so buffered
chunks are not stranded when Node 26 emits one readable event
per push instead of coalescing multiple pushes
- switch assertion from 'finish' to 'end' event so it runs after
the readable side has fully drained, not just after writable done
- convert nearby var to let/const per project style
Background: how a Transform stream signals completion
=====================================================
A Transform stream is both a Writable (input side) and a Readable
(output side). Each side has its own "done" event:
- 'finish' — writable side done: no more write() calls, and all
buffered writes have been processed by _transform / _flush.
- 'end' — readable side done: consumer has read every chunk
the stream will ever produce, and the buffer is now empty.
'finish' always fires first; 'end' fires only after the readable
buffer is fully drained by the consumer.
Producer side Consumer side
(writable) (readable)
----------- ----------
write(0) --> _transform --push('[0')--> +--------+
| buffer |
write(1) --> _transform --push(',1')--> | [0 |
| ,1 |
write(2) --> _transform --push(',2')--> | ,2 |
| ] |
end() --> _flush --push( ']')--> +--------+
| |
v |
+--------+ |
| finish | <-- writable done |
+--------+ (no more input) |
|
consumer drains buffer |
via read() loop |
v
+----------+
| buffer |
| drained |
| + EOF |
+----------+
|
v
+--------+
| end | <-- readable done
+--------+
How 'readable' events are scheduled: Node < 26 vs Node 26
---------------------------------------------------------
Node < 26 — pushes coalesce into one 'readable':
push('[0') ┐
push(',1') |
push(',2') | all 4 pushes land in buffer
push(']') ┘ before microtasks flush
|
v
+----------------------+
| ONE 'readable' fires |
+----------------------+
|
v
read() --> "[0,1,2]" (all 4 concatenated)
read() --> null (buffer empty)
|
v
'finish' data == "[0,1,2]" ✓
The buggy single-read-per-event handler happened to work
because one read() call retrieved everything.
Node 26 — each push tends to fire its own 'readable':
push('[0') --> 'readable' no.1 --> read() --> "[0"
push(',1') --> 'readable' no.2 --> read() --> ",1"
push(',2') --> 'readable' no.3 --> (queued, not yet delivered)
push(']') --> 'readable' no.4 --> (queued, not yet delivered)
|
v
'finish' fires here
|
v
handler runs assertion: data == "[0,1" ✗
|
v
(later) events no.3, no.4 deliver — too late
Only two chunks reach the accumulator; the remaining two are
still in the readable buffer when 'finish' fires. JSON.parse
sees a truncated string and throws.
The fix
-------
Draining with \`while ((chunk = read()) !== null)\` empties the
buffer per event regardless of how many chunks it holds, and
asserting on 'end' waits until the readable side is fully done.
Both align with the documented stream contract and work on all
Node versions.
… to 3s
- add this.timeout(3000) to the REAL_VECTOR (dynamic length) 'should
raise input type error' test to accommodate accumulated latency from
6 invalid-input round-trips via async.each on far HANA cloud servers
- leave other DataType tests at Mocha's 2s default
- delete test/mocha.opts, which has been silently ignored since the
repo upgraded to Mocha 8+ (mocha.opts was deprecated in v6, removed
in v8; current version is 11)
- --require should was already redundant: several test files
(lib.Writer.js, lib.Reader.js, hdb.Client.js, util.bignum.js,
rep.part.js, acceptance/db.Authentication.js) require('should')
directly, and once any of them runs the Object.prototype mutation
covers the whole process
- --growl referenced growlnotify (dead since ~2016) and was removed
from Mocha in v7; would be a hard error if the file were parsed
Co-authored-by: Michal Majewski <michal.majewski@sap.com>
- add .github/workflows/backport.yml that uses korthout/backport-action
to auto-cherry-pick merged PRs to rel/* branches when labeled with
`backport rel/<version>`
- fires on pull_request_target (closed, labeled); creates a backport PR
for each matching label; conflicts leave conflict markers in the PR
for manual resolution
- restricts label pattern to `^backport (rel/[^ ]+)$` so only rel/*
branches can be targeted
- pin actions/checkout to df4cb1c (v6.0.3) and korthout/backport-action
to 2e830a1 (v4.6.0) to make the audited action code immutable — a
moved tag on pull_request_target with write permissions would
otherwise be a supply-chain foothold
…tHub
- change runs-on from `ubuntu-latest` to `[self-hosted, solinas]`; SAP's
internal GitHub has no GitHub-hosted runners, so `ubuntu-latest` jobs
queue forever with no runner to pick them up
- align with the SUGAR runner label already used by integration-test.yml
* Update Client.js
* Update Connection.js
* Create ConnectOptionFlagSet1.js
* Update ConnectOption.js
* Update ConnectOptionType.js
* Update MessageType.js
* Update index.js
* Update index.js
* Update ConnectOptionFlagSet1.js
* Update Connection.js
* Update ConnectOptions.js
* Update index.js
* Update index.js
* Update db.Lifecycle.js
* Update Connection.js
* Update PartKind.js
* Update Connection.js
* Update Connection.js
* Keep space for potential client info updates
* [FIX] keep space for potential client info update segments
- fix getUpdatedPropertiesSize to compute exact wire size of the
CLIENT_INFO part, accounting for per-field length indicators,
8-byte alignment, PART_HEADER_LENGTH, and useCesu8 encoding
- return 0 when no properties are pending, removing the need for
a message-type gate in getAvailableSize
* [TEST] add acceptance test for LOB exec with pending client info
- verify that setting client info between prepare and exec does not
cause Packet size limit exceeded when writing a LOB stream
---------
Co-authored-by: Bob den Os <bob.den.os@sap.com>
@linjun-he-sap
linjun-he-sap merged commit f26df55 into masterAug 14, 2026
1 check passed
@linjun-he-sap
linjun-he-sap deleted the mirroring/2.29.6 branch August 14, 2026 17:09
Sign up for freeto 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.

4 participants

@linjun-he-sap@jeffalbion@ianmchardy@davidbrandow