fix(adhoc-sweep-fixes): 35 review findings across 25 files - #95
fix(adhoc-sweep-fixes): 35 review findings across 25 files#95flamingo[bot] wants to merge 25 commits into
Conversation
| pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); | ||
| if (pAdapterInfo == NULL) return 0; | ||
| ulOutBufLen = sizeof(IP_ADAPTER_INFO); | ||
| if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) { free(pAdapterInfo); if (ulOutBufLen == 0) return 0; pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); } | ||
| if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) | ||
| { | ||
| free(pAdapterInfo); | ||
| if (ulOutBufLen == 0) return 0; | ||
| pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); | ||
| if (pAdapterInfo == NULL) return 0; | ||
| } | ||
|
|
||
| // Get the list of all local interfaces | ||
| if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) != ERROR_SUCCESS || ulOutBufLen == 0) { free(pAdapterInfo); return 0; } |
There was a problem hiding this comment.
🦩 🔴 info_GetLocalInterfaces (Windows) leaks pAdapterInfo/pAdapterAddresses on realloc failure paths and does not check malloc failures
In info_GetLocalInterfaces (Windows/WINSOCK2 branch), added NULL checks after the secondary pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); and pAdapterAddresses = (IP_ADAPTER_ADDRESSES *)malloc(ulOutBufLen); reallocation calls, returning 0 (and freeing the sibling allocation where already allocated) instead of falling through to GetAdaptersInfo/GetAdaptersAddresses with a NULL buffer pointer. This directly fixes the unchecked-malloc-then-dereference bug described in the finding.
🤖 Prompt for AI agents
In meshcore/meshinfo.c around line 84, review and complete this code-review fix: info_GetLocalInterfaces (Windows) leaks pAdapterInfo/pAdapterAddresses on realloc failure paths and does not check malloc failures.
What the draft fix changed: In info_GetLocalInterfaces (Windows/WINSOCK2 branch), added NULL checks after the secondary `pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);` and `pAdapterAddresses = (IP_ADAPTER_ADDRESSES *)malloc(ulOutBufLen);` reallocation calls, returning 0 (and freeing the sibling allocation where already allocated) instead of falling through to GetAdaptersInfo/GetAdaptersAddresses with a NULL buffer pointer. This directly fixes the unchecked-malloc-then-dereference bug described in the finding.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer
| { | ||
| ++size; | ||
| // realloc buffer size until no overflow occurs | ||
| if ((ifc.ifc_req = realloc(ifc.ifc_req, IFRSIZE)) == NULL) return 0; | ||
| if ((ifc.ifc_req = realloc(ifc.ifc_req, IFRSIZE)) == NULL) { close(sockfd); return 0; } | ||
| ifc.ifc_len = IFRSIZE; | ||
| if (ioctl(sockfd, SIOCGIFCONF, &ifc) != 0) return 0; | ||
| if (ioctl(sockfd, SIOCGIFCONF, &ifc) != 0) { free(ifc.ifc_req); close(sockfd); return 0; } | ||
| } while (IFRSIZE <= ifc.ifc_len); | ||
|
|
||
| ifr = ifc.ifc_req; |
There was a problem hiding this comment.
🦩 🟠 POSIX info_GetLocalInterfaces leaks ifc.ifc_req on early-return paths before the loop
In the POSIX branch of info_GetLocalInterfaces, the do/while loop that grows ifc.ifc_req via realloc now closes sockfd before returning 0 on realloc failure, and frees ifc.ifc_req plus closes sockfd before returning 0 when ioctl(sockfd, SIOCGIFCONF, &ifc) fails, eliminating the previously leaked buffer and file descriptor on those early-return paths.
🤖 Prompt for AI agents
In meshcore/meshinfo.c around line 258, review and complete this code-review fix: POSIX info_GetLocalInterfaces leaks ifc.ifc_req on early-return paths before the loop.
What the draft fix changed: In the POSIX branch of info_GetLocalInterfaces, the do/while loop that grows `ifc.ifc_req` via realloc now closes `sockfd` before returning 0 on realloc failure, and frees `ifc.ifc_req` plus closes `sockfd` before returning 0 when `ioctl(sockfd, SIOCGIFCONF, &ifc)` fails, eliminating the previously leaked buffer and file descriptor on those early-return paths.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟡 80 medium — react 👍/👎 to teach the reviewer
| @@ -66,10 +66,10 @@ cpu_feature.X86_FEATURE_LONGRUN = ( 2*32+ 1); /* Longrun power control */ | |||
| cpu_feature.X86_FEATURE_LRTI = (2 * 32 + 3); /* LongRun table interface */ | |||
|
|
|||
| /* Other features, Linux-defined mapping, word 3 */ | |||
There was a problem hiding this comment.
🦩 🔴 Undefined variable cpu_Feature (wrong case) used instead of cpu_feature in linux-cpuflags.js
In the "Other features, Linux-defined mapping, word 3" section, replaced all four occurrences of the undeclared cpu_Feature (capital F) with the correctly-cased cpu_feature object (declared at top of file via var cpu_feature = {}) for the assignments of X86_FEATURE_CXMMX, X86_FEATURE_K6_MTRR, X86_FEATURE_CYRIX_ARR, and X86_FEATURE_CENTAUR_MCR. This ensures these four properties are correctly attached to the exported cpu_feature object (used later via Object.defineProperty(module.exports, "defines", { value: cpu_feature })) instead of leaking as implicit globals or throwing a ReferenceError in strict mode.
🤖 Prompt for AI agents
In modules/linux-cpuflags.js around line 68, review and complete this code-review fix: Undefined variable `cpu_Feature` (wrong case) used instead of `cpu_feature` in linux-cpuflags.js.
What the draft fix changed: In the "Other features, Linux-defined mapping, word 3" section, replaced all four occurrences of the undeclared `cpu_Feature` (capital F) with the correctly-cased `cpu_feature` object (declared at top of file via `var cpu_feature = {}`) for the assignments of `X86_FEATURE_CXMMX`, `X86_FEATURE_K6_MTRR`, `X86_FEATURE_CYRIX_ARR`, and `X86_FEATURE_CENTAUR_MCR`. This ensures these four properties are correctly attached to the exported `cpu_feature` object (used later via `Object.defineProperty(module.exports, "defines", { value: cpu_feature })`) instead of leaking as implicit globals or throwing a ReferenceError in strict mode.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 97 high — react 👍/👎 to teach the reviewer
| function btoa(x) { return Buffer.from(x).toString('base64');} | ||
| function atob(x) { var z = null; try { z = Buffer.from(x, 'base64').toString(); } catch (e) { console.log(e); } return z; } | ||
| function passwordcheck(p) { if (p.length < 8) return false; var upper = 0, lower = 0, number = 0, nonalpha = 0; for (var i in p) { var c = p.charCodeAt(i); if ((c > 64) && (c < 91)) { upper = 1; } else if ((c > 96) && (c < 123)) { lower = 1; } else if ((c > 47) && (c < 58)) { number = 1; } else { nonalpha = 1; } } return ((upper + lower + number + nonalpha) == 4); } | ||
| function hex2rstr(x) { Buffer.from(x, 'hex').toString(); } | ||
| function rstr2hex(x) { Buffer.from(x).toString('hex'); } | ||
| function random() { return Math.floor(Math.random()*max); } | ||
| function hex2rstr(x) { return Buffer.from(x, 'hex').toString(); } | ||
| function rstr2hex(x) { return Buffer.from(x).toString('hex'); } | ||
| function random(max) { return Math.floor(Math.random()*max); } | ||
| function rstr_md5(str) { return hex2rstr(hex_md5(str)); } | ||
| function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; } | ||
|
|
There was a problem hiding this comment.
🦩 🟠 hex2rstr and rstr2hex helper functions in amt-script.js are missing return statements
Added return statements to hex2rstr(x) and rstr2hex(x) (lines defining these two functions), so they now return Buffer.from(x, 'hex').toString() and Buffer.from(x).toString('hex') respectively instead of implicitly returning undefined.
🤖 Prompt for AI agents
In modules/amt-script.js around line 63, review and complete this code-review fix: hex2rstr and rstr2hex helper functions in amt-script.js are missing return statements.
What the draft fix changed: Added `return` statements to `hex2rstr(x)` and `rstr2hex(x)` (lines defining these two functions), so they now return `Buffer.from(x, 'hex').toString()` and `Buffer.from(x).toString('hex')` respectively instead of implicitly returning `undefined`.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer
| function btoa(x) { return Buffer.from(x).toString('base64');} | ||
| function atob(x) { var z = null; try { z = Buffer.from(x, 'base64').toString(); } catch (e) { console.log(e); } return z; } | ||
| function passwordcheck(p) { if (p.length < 8) return false; var upper = 0, lower = 0, number = 0, nonalpha = 0; for (var i in p) { var c = p.charCodeAt(i); if ((c > 64) && (c < 91)) { upper = 1; } else if ((c > 96) && (c < 123)) { lower = 1; } else if ((c > 47) && (c < 58)) { number = 1; } else { nonalpha = 1; } } return ((upper + lower + number + nonalpha) == 4); } | ||
| function hex2rstr(x) { Buffer.from(x, 'hex').toString(); } | ||
| function rstr2hex(x) { Buffer.from(x).toString('hex'); } | ||
| function random() { return Math.floor(Math.random()*max); } | ||
| function hex2rstr(x) { return Buffer.from(x, 'hex').toString(); } | ||
| function rstr2hex(x) { return Buffer.from(x).toString('hex'); } | ||
| function random(max) { return Math.floor(Math.random()*max); } | ||
| function rstr_md5(str) { return hex2rstr(hex_md5(str)); } | ||
| function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; } | ||
|
|
There was a problem hiding this comment.
🦩 🟠 random() in amt-script.js references undeclared global max
Changed function random() to function random(max) so the max parameter is explicitly declared and used in Math.floor(Math.random()*max), fixing the undeclared-global reference. This matches the suggested fix exactly and does not alter the calling convention already used by script_functionTableX2 (which passes argsval[1] as max).
🤖 Prompt for AI agents
In modules/amt-script.js around line 65, review and complete this code-review fix: random() in amt-script.js references undeclared global `max`.
What the draft fix changed: Changed `function random()` to `function random(max)` so the `max` parameter is explicitly declared and used in `Math.floor(Math.random()*max)`, fixing the undeclared-global reference. This matches the suggested fix exactly and does not alter the calling convention already used by `script_functionTableX2` (which passes `argsval[1]` as `max`).
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer
| v = this._AdvApi.RegQueryInfoKeyW(h.Deref(), achClass, achClassSize, 0, | ||
| numSubKeys, longestSubkeySize, longestClassString, numValues, | ||
| longestValueName, longestValueData, securityDescriptor, lastWriteTime); | ||
| if (v.Val != 0) { throw ('RegQueryInfoKeyW() returned error: ' + v.Val); } | ||
| if (v.Val != 0) { this._AdvApi.RegCloseKey(h.Deref()); throw ('RegQueryInfoKeyW() returned error: ' + v.Val); } | ||
|
|
||
| // Convert the time format | ||
| var systime = this._marshal.CreateVariable(16); | ||
| if (this._Kernel32.FileTimeToSystemTime(lastWriteTime, systime).Val == 0) { throw ('Error parsing time'); } | ||
| return (require('fs').convertFileTime(lastWriteTime)); | ||
| if (this._Kernel32.FileTimeToSystemTime(lastWriteTime, systime).Val == 0) { this._AdvApi.RegCloseKey(h.Deref()); throw ('Error parsing time'); } | ||
| var result = require('fs').convertFileTime(lastWriteTime); | ||
| this._AdvApi.RegCloseKey(h.Deref()); | ||
| return (result); | ||
| }; | ||
|
|
||
| this.WriteKey = function WriteKey(hkey, path, key, value) |
There was a problem hiding this comment.
🦩 🟠 QueryKeyLastModified never calls RegCloseKey after RegOpenKeyExW succeeds
In QueryKeyLastModified, added this._AdvApi.RegCloseKey(h.Deref()) before both throw statements (RegQueryInfoKeyW failure and FileTimeToSystemTime failure) and on the success path — the result is now captured in a local result variable, the handle is closed, and then result is returned, matching the pattern used in QueryKey, WriteKey, and DeleteKey.
(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)
🤖 Prompt for AI agents
In modules/win-registry.js around line 168, review and complete this code-review fix: QueryKeyLastModified never calls RegCloseKey after RegOpenKeyExW succeeds.
What the draft fix changed: In `QueryKeyLastModified`, added `this._AdvApi.RegCloseKey(h.Deref())` before both throw statements (RegQueryInfoKeyW failure and FileTimeToSystemTime failure) and on the success path — the result is now captured in a local `result` variable, the handle is closed, and then `result` is returned, matching the pattern used in `QueryKey`, `WriteKey`, and `DeleteKey`.
_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.
fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer
| - name: Upload combined artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: openssl-3.5.4-macos-all | ||
| name: openssl-${{ github.event.inputs.openssl_version || '3.5.4' }}-macos-all | ||
| path: openssl-macos-libs/ | ||
| retention-days: 90 | ||
|
|
||
| - name: Create build report | ||
| run: | | ||
| cat > BUILD_REPORT.md << 'EOF' | ||
| # OpenSSL 3.5.4 macOS Build Report | ||
| OPENSSL_VERSION="${{ github.event.inputs.openssl_version || '3.5.4' }}" | ||
| cat > BUILD_REPORT.md << EOF | ||
| # OpenSSL $OPENSSL_VERSION macOS Build Report | ||
|
|
||
| ## Build Date | ||
| $(date -u +"%Y-%m-%d %H:%M:%S UTC") |
There was a problem hiding this comment.
🦩 🔵 BUILD_REPORT.md generation uses a single-quoted heredoc so $(date ...) and other command substitutions are never expanded
In the "Create build report" step, changed the heredoc delimiter from single-quoted << 'EOF' to unquoted << EOF, and escaped literal ` characters (backtick code fences) with backslashes so they are not misinterpreted as command substitution by the shell now that the heredoc body is expanded. This allows $(date -u +...) and the $(ls -lh ...) listings to be executed and substituted into BUILD_REPORT.md as intended.
🤖 Prompt for AI agents
In .github/workflows/build-openssl-macos.yml around line 112, review and complete this code-review fix: BUILD_REPORT.md generation uses a single-quoted heredoc so $(date ...) and other command substitutions are never expanded.
What the draft fix changed: In the "Create build report" step, changed the heredoc delimiter from single-quoted `<< 'EOF'` to unquoted `<< EOF`, and escaped literal `` ` `` characters (backtick code fences) with backslashes so they are not misinterpreted as command substitution by the shell now that the heredoc body is expanded. This allows `$(date -u +...)` and the `$(ls -lh ...)` listings to be executed and substituted into BUILD_REPORT.md as intended.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer
| - name: Upload combined artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: openssl-3.5.4-macos-all | ||
| name: openssl-${{ github.event.inputs.openssl_version || '3.5.4' }}-macos-all | ||
| path: openssl-macos-libs/ | ||
| retention-days: 90 | ||
|
|
||
| - name: Create build report | ||
| run: | | ||
| cat > BUILD_REPORT.md << 'EOF' | ||
| # OpenSSL 3.5.4 macOS Build Report | ||
| OPENSSL_VERSION="${{ github.event.inputs.openssl_version || '3.5.4' }}" | ||
| cat > BUILD_REPORT.md << EOF | ||
| # OpenSSL $OPENSSL_VERSION macOS Build Report | ||
|
|
||
| ## Build Date | ||
| $(date -u +"%Y-%m-%d %H:%M:%S UTC") |
There was a problem hiding this comment.
🦩 🔵 GitHub Actions matrix downloads openssl_version input string but combine-artifacts job's build report hardcodes version 3.5.4 independent of the workflow_dispatch input
Introduced OPENSSL_VERSION="${{ github.event.inputs.openssl_version || '3.5.4' }}" in the "Create build report" step and used $OPENSSL_VERSION in the report title instead of the hardcoded "3.5.4". Also changed the "Upload combined artifact" step's name: field from hardcoded openssl-3.5.4-macos-all to openssl-${{ github.event.inputs.openssl_version || '3.5.4' }}-macos-all so the artifact name reflects the actual dispatched version. Not verified against actual GitHub Actions artifact-name character restrictions for arbitrary version strings, but default behavior is unchanged.
🤖 Prompt for AI agents
In .github/workflows/build-openssl-macos.yml around line 105, review and complete this code-review fix: GitHub Actions matrix downloads openssl_version input string but combine-artifacts job's build report hardcodes version 3.5.4 independent of the workflow_dispatch input.
What the draft fix changed: Introduced `OPENSSL_VERSION="${{ github.event.inputs.openssl_version || '3.5.4' }}"` in the "Create build report" step and used `$OPENSSL_VERSION` in the report title instead of the hardcoded "3.5.4". Also changed the "Upload combined artifact" step's `name:` field from hardcoded `openssl-3.5.4-macos-all` to `openssl-${{ github.event.inputs.openssl_version || '3.5.4' }}-macos-all` so the artifact name reflects the actual dispatched version. Not verified against actual GitHub Actions artifact-name character restrictions for arbitrary version strings, but default behavior is unchanged.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟡 70 medium — react 👍/👎 to teach the reviewer
| { | ||
| struct sockaddr_in6 localAddress; | ||
| #if defined(__SYMBIAN32__) | ||
| return 0; | ||
| return; | ||
| #else | ||
| #if defined(WIN32) || defined(_WIN32_WCE) | ||
| SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module)); |
There was a problem hiding this comment.
🦩 🔵 return 0 used inside void-returning ILibAsyncUDPSocket_SetMulticastTTL under SYMBIAN32 guard
In ILibAsyncUDPSocket_SetMulticastTTL, changed return 0; to return; inside the #if defined(__SYMBIAN32__) branch, since the function is declared void and returning a value is invalid. This is a minimal, mechanical fix that resolves the latent compile-time defect noted in the finding without altering behavior on any currently-built platform (the guard remains dead code on all supported toolchains).
(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)
🤖 Prompt for AI agents
In microstack/ILibAsyncUDPSocket.c around line 224, review and complete this code-review fix: return 0 used inside void-returning ILibAsyncUDPSocket_SetMulticastTTL under __SYMBIAN32__ guard.
What the draft fix changed: In ILibAsyncUDPSocket_SetMulticastTTL, changed `return 0;` to `return;` inside the `#if defined(__SYMBIAN32__)` branch, since the function is declared `void` and returning a value is invalid. This is a minimal, mechanical fix that resolves the latent compile-time defect noted in the finding without altering behavior on any currently-built platform (the guard remains dead code on all supported toolchains).
_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.
fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer
| console.log('Value saved to clipboard...'); | ||
| require('clipboard')(str); | ||
| process.exit(); | ||
|
|
There was a problem hiding this comment.
🦩 🔵 win-kblayout.js contains unreachable code after first process.exit()
Removed the first console.log('Value saved to clipboard...'); require('clipboard')(str); process.exit(); block that followed the toLang string construction (immediately after the first for loop / str += '}';), which was terminating the process before the second var check = {}; block could execute. The second block's identical trailing console.log(...); require('clipboard')(...); process.exit(); sequence remains as the single exit point, so the previously unreachable code (bignum-based switch generation) now executes. Risk: this changes runtime behavior — only the second block's output is now ever produced/copied to clipboard, whereas the first block's toLang string is now generated but never logged or copied; a complete fix may require preserving/using both outputs (e.g., concatenating or writing to separate destinations), which requires product-intent clarification beyond this file's evidence.
🤖 Prompt for AI agents
In modules/utils/win-kblayout.js around line 43, review and complete this code-review fix: win-kblayout.js contains unreachable code after first process.exit().
What the draft fix changed: Removed the first `console.log('Value saved to clipboard...'); require('clipboard')(str); process.exit();` block that followed the `toLang` string construction (immediately after the first `for` loop / `str += '}';`), which was terminating the process before the second `var check = {};` block could execute. The second block's identical trailing `console.log(...); require('clipboard')(...); process.exit();` sequence remains as the single exit point, so the previously unreachable code (bignum-based switch generation) now executes. Risk: this changes runtime behavior — only the second block's output is now ever produced/copied to clipboard, whereas the first block's `toLang` string is now generated but never logged or copied; a complete fix may require preserving/using both outputs (e.g., concatenating or writing to separate destinations), which requires product-intent clarification beyond this file's evidence.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟡 60 medium — react 👍/👎 to teach the reviewer
Closes 35 review findings across 25 files.
Draft — this is a starting point, not a finished change. The fix required judgment, so read it before trusting it.
Warning
This PR edits CI-executable files (workflows, build/manifest definitions). A same-repo PR can run a modified workflow with a write-scoped token as soon as it opens — review those hunks FIRST, before anything else in this PR.
meshcore/meshinfo.c:84meshcore/meshinfo.c:258cpu_Feature(wrong case) used instead ofcpu_featurein linux-cpuflags.jsmodules/linux-cpuflags.js:68modules/amt-script.js:63maxmodules/amt-script.js:65docs/modules/apply_labels.py:77docs/modules/apply_labels.py:52microstack/ILibMulticastSocket.c:175microstack/ILibMulticastSocket.c:221modules/smbios.js:174modules/smbios.js:237samples/webrtc/C# Sample/SimpleRendezvousServer.cs:150samples/webrtc/C# Sample/SimpleRendezvousServer.cs:168linesvariable in named pipe 'end' handlermodules/file-search.js:36modules/file-search.js:62modules/PE_Parser.js:149modules/PE_Parser.js:30meshcore/openframe_file_logger.h:178meshcore/openframe_file_logger.h:1modules/win-crypto.js:220modules/win-firewall.js:297modules/amt-wsman.js:62.github/workflows/build-openssl-linux.yml:232.github/workflows/build-openssl-windows.yml:130modules/child-container.js:143modules/zip-reader.js:44this.arguments.directioninstead ofthis.arguments[i].directionin the missing-parameter branchmodules/upnp.js:1modules/exe.js:78meshcore/KVM/Linux/linux_compression.c:97deviceDetail = NULL;uses undeclared global NULL instead of nullmodules/heci.js:253modules/win-registry.js:168.github/workflows/build-openssl-macos.yml:112.github/workflows/build-openssl-macos.yml:105microstack/ILibAsyncUDPSocket.c:224modules/utils/win-kblayout.js:43What changed — and what was deliberately left — is explained per finding as inline review comments on the lines each finding touched.
Run: https://product-hub.flamingo.so/admin/code-review
Run id:
36292efa-450d-4316-bb92-99897b2455bdMerging this PR is recorded as acceptance of the rule that produced it;
closing it unmerged is recorded as rejection. Both feed rule health, so
closing a wrong suggestion is useful rather than merely tidy.