Skip to content

Commit 476d851

Browse files
Copilotdummdidumm
andcommitted
Fix prerender memory issue with circular references from meta tags
Co-authored-by: dummdidumm <[email protected]>
1 parent 0ec229d commit 476d851

File tree

4 files changed

+39
-28
lines changed

4 files changed

+39
-28
lines changed

packages/kit/src/core/postbuild/crawl.js

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -230,29 +230,7 @@ export function crawl(html, base) {
230230
const attr = name ?? property;
231231

232232
if (attr && CRAWLABLE_META_NAME_ATTRS.has(attr)) {
233-
const resolved = resolve(base, content);
234-
// Check for malformed URLs with consecutive slashes in the path
235-
// Allow protocol-relative URLs (//example.com) and normal URLs (https://example.com)
236-
// Block URLs with double slashes in paths (/path//file or domain//file)
237-
let shouldInclude = true;
238-
if (resolved.includes('//')) {
239-
// If it starts with // it's protocol-relative, which is fine
240-
if (resolved.startsWith('//')) {
241-
shouldInclude = true;
242-
}
243-
// If it contains :// it's a full URL, which is fine
244-
else if (resolved.includes('://')) {
245-
shouldInclude = true;
246-
}
247-
// Otherwise it's a malformed path with double slashes
248-
else {
249-
shouldInclude = false;
250-
}
251-
}
252-
253-
if (shouldInclude) {
254-
hrefs.push(resolved);
255-
}
233+
hrefs.push(resolve(base, content));
256234
}
257235
}
258236
}

packages/kit/src/core/postbuild/prerender.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,26 @@ async function prerender({ hash, out, manifest_path, metadata, verbose, env }) {
221221
const file = decoded.slice(config.paths.base.length + 1);
222222
if (files.has(file)) return;
223223

224+
// Check for URLs that contain the prerender origin hostname in the path
225+
// This can happen when meta tags reference URLs like "{page.url.host}/file.jpg"
226+
// and can cause infinite loops during prerendering
227+
if (config.prerender.origin !== 'http://sveltekit-prerender') {
228+
// Extract hostname from prerender origin
229+
const prerenderHost = new URL(config.prerender.origin).hostname;
230+
// Check if the path starts with the prerender hostname (avoiding circular references)
231+
if (decoded.startsWith(`/${prerenderHost}/`)) {
232+
// This looks like a circular reference - handle as 404
233+
handle_http_error({ status: 404, path: decoded, referrer, referenceType: 'linked' });
234+
return;
235+
}
236+
} else {
237+
// For the default sveltekit-prerender origin, check for the specific pattern
238+
if (decoded.startsWith('/sveltekit-prerender/')) {
239+
handle_http_error({ status: 404, path: decoded, referrer, referenceType: 'linked' });
240+
return;
241+
}
242+
}
243+
224244
return q.add(() => visit(decoded, encoded || encodeURI(decoded), referrer, generated_from_id));
225245
}
226246

@@ -258,7 +278,13 @@ async function prerender({ hash, out, manifest_path, metadata, verbose, env }) {
258278
}
259279

260280
// stuff in `static`
261-
return readFileSync(join(config.files.assets, file));
281+
const static_path = join(config.files.assets, file);
282+
// Check if the static file exists before trying to read it
283+
// This prevents potential issues with malformed paths or non-existent files
284+
if (!existsSync(static_path)) {
285+
throw new Error(`Static file not found: ${file}`);
286+
}
287+
return readFileSync(static_path);
262288
},
263289
emulator
264290
});

packages/kit/test/build-errors/apps/prerender-meta-static-reference/src/routes/+layout.svelte

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
<script>
2+
import { page } from '$app/stores';
3+
24
let dynamic_title = 'My Page';
35
let dynamic_desc = 'Description';
6+
// Simulate the original user's scenario where paths might have leading slashes
7+
let a_path_to_svelte_kit_static_content = '/me.jpg'; // This would create double slashes
48
</script>
59

610
<svelte:head>
711
<meta property="og:title" content={dynamic_title} />
812
<meta property="og:description" content={dynamic_desc} />
9-
<meta property="og:url" content="http://sveltekit-prerender" />
10-
<meta property="og:image" content="sveltekit-prerender//me.jpg" />
13+
<meta property="og:url" content={$page.url.origin} />
14+
<meta property="og:image" content="{$page.url.host}/{a_path_to_svelte_kit_static_content}" />
1115
</svelte:head>
1216

1317
<slot />

packages/kit/test/build-errors/prerender-meta-static-reference.spec.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ test('should handle HTTP errors in meta tags without infinite loop', { timeout }
1414
encoding: 'utf8'
1515
});
1616

17-
// The build should succeed and warn about favicon.png but not about malformed URLs
17+
// The build should succeed and handle the circular reference properly
1818
assert.match(result, /404.*favicon\.png/);
19-
assert.ok(!result.includes('sveltekit-prerender//image'), 'Should not contain malformed URLs with double slashes');
19+
// Should handle the circular reference from meta tag
20+
assert.match(result, /404.*sveltekit-prerender.*me\.jpg/);
21+
// Should complete successfully
22+
assert.match(result, / done/);
2023
});

0 commit comments

Comments
 (0)