Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/chat-app/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ function parseBlocks(text: string): Block[] {
}

// ── Handle Paragraphs ────────────────────────
if (line.trim() === '') {
if (line.trim().length === 0) {
blocks.push({
type: 'paragraph',
text: '',
Expand Down
2 changes: 1 addition & 1 deletion examples/rss-reader/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function decodeEntities(value: string): string {

return value.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (match, entity: string) => {
if (entity.startsWith('#x')) {
const codePoint = Number.parseInt(entity.slice(2), 16);
const codePoint = Number.parseInt(entity.slice(2, 10), 16);
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;
Comment on lines 28 to 31

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does JavaScript String.fromCodePoint throw RangeError for values greater than 0x10FFFF?

💡 Result:

Yes, the JavaScript String.fromCodePoint method throws a RangeError if any of the provided arguments are greater than 0x10FFFF [1][2]. According to the ECMAScript specification, String.fromCodePoint iterates through its arguments and performs a check to ensure each is a valid Unicode code point [3][4]. A value is considered invalid if it is not an integral number, is less than 0, or is greater than 0x10FFFF [3][4]. If any of these conditions are met, the method throws a RangeError exception [1][3]. This behavior is consistent across all modern JavaScript environments as defined by the ECMAScript standard [3][5][6][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the referenced file and decoding implementation.
if [ -f examples/rss-reader/src/index.tsx ]; then
  wc -l examples/rss-reader/src/index.tsx
  sed -n '1,80p' examples/rss-reader/src/index.tsx | cat -n
else
  echo "File examples/rss-reader/src/index.tsx not found"
  fd -i 'index\.tsx$' . | sed -n '1,40p'
fi

# Find any related tests or usages that may affect severity.
printf '\nSearch for decodeEntity/replace/unescape references:\n'
rg -n "decodeEntity|unescape|&`#x`?|`#x`|[0-9a-fA-F]+;|String\.fromCodePoint|parseInt" examples/rss-reader/src examples/rss-reader 2>/dev/null || true

# Read-only behavioral probe matching the relevant parser slice semantics.
node - <<'JS'
function decodeCurrent(value) {
  return value.replace(/&(`#x`?[0-9a-fA-F]+|[a-zA-Z]+);/g, (match, entity) => {
    if (entity.startsWith('`#x`')) {
      const codePoint = Number.parseInt(entity.slice(2, 10), 16);
      return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;
    }
    return match;
  });
}
const inputs = [
  '&amp;',
  '&`#x61`;',
  '&`#x10ffff`;',
  '&`#x110000`;',
  '&`#x110000ffffff`;',
  '&`#110000`;',
];
for (const input of inputs) {
  try {
    console.log(JSON.stringify(input), '=>', JSON.stringify(decodeCurrent(input)));
  } catch (error) {
    console.log(JSON.stringify(input), 'THREW', error.name + ': ' + error.message);
  }
}
JS

Repository: Karanjot786/TermUI

Length of output: 5558


Reject overlong and invalid hexadecimal entities.

entity.slice(2, 10) can turn longer malformed entities into valid values or pass values above 0x10ffff to String.fromCodePoint, which throws RangeError and stops RSS parsing. Skip entities with more than eight hexadecimal digits before parsing, validate codePoint <= 0x10ffff before conversion, and apply the same range check to decimal numeric entities.

Proposed fix
 if (entity.startsWith('`#x`')) {
-  const codePoint = Number.parseInt(entity.slice(2, 10), 16);
-  return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;
+  const digits = entity.slice(2);
+  if (digits.length > 8) return match;
+  const codePoint = Number.parseInt(digits, 16);
+  return codePoint <= 0x10ffff ? String.fromCodePoint(codePoint) : match;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/rss-reader/src/index.tsx` around lines 28 - 31, Update the
entity-decoding callback to reject hexadecimal entities containing more than
eight digits before parsing, and require parsed numeric values to be within
0x000000–0x10FFFF before calling String.fromCodePoint. Apply the same
upper-bound validation to decimal numeric entities, returning the original match
for invalid or out-of-range values so RSS parsing continues safely.

}

Expand Down
2 changes: 1 addition & 1 deletion examples/widget-gallery/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class WidgetGalleryApp extends Widget {
}

// Tab switching: 1-6
const num = parseInt(event.key);
const num = parseInt(event.key, 10);
if (num >= 1 && num <= 6) {
this._switchTab(num - 1);
return true;
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/Form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,5 @@ export class Form extends Widget {
}
}
}

.catch(err => console.error("Promise.all failed:", err));
Comment on lines +141 to +142

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Attach the rejection handler to the Promise expression.

Line 142 is a standalone .catch(...) expression. Biome reports a parse error, so packages/ui/src/Form.ts cannot compile. Attach .catch(...) directly to Promise.all(...), or use try/catch and rethrow after logging.

try {
    const results = await Promise.all(existingPromises);
    // Existing result handling.
} catch (err) {
    console.error("Promise.all failed:", err);
    throw err;
}
🧰 Tools
🪛 Biome (2.5.6)

[error] 142-142: Expected a statement but instead found '.catch(err => console.error("Promise.all failed:", err))'.

(parse)

🪛 GitHub Actions: CI / 0_build-and-test.txt

[error] 142-142: @termuijs/ui build failed during tsup/esbuild: unexpected '.' at the standalone '.catch(err => console.error("Promise.all failed:", err));'. TypeScript also reported TS1128, TS1005, and TS2304 syntax errors. Command: bun run build.

🪛 GitHub Actions: CI / build-and-test

[error] 142-142: The @termuijs/ui build failed during tsup/esbuild: unexpected '.' in .catch(err => console.error("Promise.all failed:", err));. TypeScript also reported syntax errors (TS1128, TS1005, TS2304). Command: bun run build.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/Form.ts` around lines 141 - 142, Fix the Promise.all handling
in Form by attaching the rejection handler directly to the Promise.all
expression, or replace it with a try/catch around the existing await and rethrow
after logging. Remove the standalone .catch expression so
packages/ui/src/Form.ts parses and compiles successfully.

Source: Linters/SAST tools

Loading