Skip to content

Commit a779799

Browse files
authored
fix(useVideoEditor): guard validateRecipe and localStorage against NaN dimensions (magic-peach#894)
NaN comparisons (NaN < 16, NaN > 7680) always evaluate to false, so a customWidth or customHeight that is NaN passes all boundary checks and validateRecipe returns null (no error). The NaN then propagates to the FFmpeg scale filter as scale=NaN:NaN, crashing the export immediately. Two fixes applied: 1. validateRecipe: prefix each custom-dimension check with Number.isNaN() so a NaN value is caught as a validation error before any comparison. 2. Legacy localStorage parser: replace bare nullish-coalescing on parsed.customWidth/customHeight with a sanitizeDimension helper that calls Number.isFinite() and enforces the [16, 7680] range. Any corrupted, non-numeric, or out-of-range stored value falls back to the previous safe default instead of being merged into state as NaN. Closes magic-peach#864
1 parent 5b24c5f commit a779799

1 file changed

Lines changed: 8 additions & 4 deletions

File tree

src/hooks/useVideoEditor.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ function validateRecipe(recipe: EditRecipe, duration: number ): string | null {
8181
"Trim start time must be earlier than the end time.",
8282
],
8383
[
84-
recipe.preset === "custom" && (recipe.customWidth < 16 || recipe.customWidth > 7680),
84+
recipe.preset === "custom" && (Number.isNaN(recipe.customWidth) || recipe.customWidth < 16 || recipe.customWidth > 7680),
8585
"Width must be between 16px and 7680px.",
8686
],
8787
[
88-
recipe.preset === "custom" && (recipe.customHeight < 16 || recipe.customHeight > 7680),
88+
recipe.preset === "custom" && (Number.isNaN(recipe.customHeight) || recipe.customHeight < 16 || recipe.customHeight > 7680),
8989
"Height must be between 16px and 7680px.",
9090
],
9191
[
@@ -248,13 +248,17 @@ export function useVideoEditor() {
248248
const saved = localStorage.getItem("reframe-settings");
249249
if (saved) {
250250
const parsed = JSON.parse(saved);
251+
const sanitizeDimension = (val: unknown, fallback: number): number => {
252+
const n = Number(val);
253+
return Number.isFinite(n) && n >= 16 && n <= 7680 ? n : fallback;
254+
};
251255
setRecipe(prev => ({
252256
...prev,
253257
preset: parsed.preset ?? prev.preset,
254258
quality: parsed.quality ?? prev.quality,
255259
speed: parsed.speed ?? prev.speed,
256-
customWidth: parsed.customWidth ?? prev.customWidth,
257-
customHeight: parsed.customHeight ?? prev.customHeight
260+
customWidth: sanitizeDimension(parsed.customWidth, prev.customWidth),
261+
customHeight: sanitizeDimension(parsed.customHeight, prev.customHeight),
258262
}));
259263
}
260264
}

0 commit comments

Comments
 (0)