fix(critical): safeSend infinite recursion + queueMicrotask, plus 6 audit findings

This commit is contained in:
Administrator 2026-06-08 22:03:19 +02:00
parent ddf2710fc6
commit 6cd7498f70
5 changed files with 38 additions and 7 deletions

View File

@ -277,7 +277,12 @@ class ConfigStore {
if (fs.existsSync(this.filePath)) {
const existing = fs.readFileSync(this.filePath, 'utf-8');
if (existing && existing.trim().length > 2) {
fs.writeFileSync(backupPath, existing, 'utf-8');
let isValid = false;
try {
const parsed = JSON.parse(existing);
isValid = parsed && typeof parsed === 'object' && (parsed.hosters || parsed.hosterSettings || parsed.globalSettings);
} catch {}
if (isValid) fs.writeFileSync(backupPath, existing, 'utf-8');
}
}
} catch {}

View File

@ -316,6 +316,7 @@ class UploadManager extends EventEmitter {
const DEDUP_CHUNK = 200;
for (let i = 0; i < tasks.length; i += DEDUP_CHUNK) {
if (signal.aborted) break;
const end = Math.min(i + DEDUP_CHUNK, tasks.length);
for (let j = i; j < end; j++) {
const task = tasks[j];
@ -334,6 +335,7 @@ class UploadManager extends EventEmitter {
const SPAWN_CHUNK = 100;
const promises = [];
for (let i = 0; i < tasks.length; i += SPAWN_CHUNK) {
if (signal.aborted) break;
const end = Math.min(i + SPAWN_CHUNK, tasks.length);
for (let j = i; j < end; j++) promises.push(this._runJob(tasks[j], results, signal));
if (end < tasks.length) await new Promise(setImmediate);

View File

@ -382,7 +382,7 @@ class VidmolyUploader {
}
}
if (best && (bestScore > 0 || newFiles.length === 1)) {
if (best && bestScore > 0) {
return this._buildUrlsFromCode(best.file_code);
}
}

View File

@ -231,7 +231,7 @@ function rotLog(msg, ts) {
function safeSend(channel, data) {
if (!mainWindow || mainWindow.isDestroyed()) return false;
try {
safeSend(channel, data);
mainWindow.webContents.send(channel, data);
return true;
} catch (err) {
debugLog(`safeSend(${channel}) failed: ${err && err.message ? err.message : err}`);
@ -1155,7 +1155,8 @@ app.on('before-quit', () => {
if (remoteServer) { remoteServer.stop(); remoteServer = null; }
destroyCaptureWindow();
} catch {}
destroyDropTargetWindow();
try { destroyDropTargetWindow(); } catch {}
try { if (tray && !tray.isDestroyed()) { tray.destroy(); tray = null; } } catch {}
// Flush pending log buffers synchronously so no lines are lost.
try {
if (_debugLogBuffer.length) {

View File

@ -2500,7 +2500,7 @@ function _computeQueueStats() {
}
_queueStatsCache = { total, remaining, inProgress, done, errors, bytesRemaining, totalSize, remainingSize, inProgressBytes };
queueMicrotask(() => { _queueStatsCache = null; });
(typeof queueMicrotask === 'function' ? queueMicrotask : (fn) => Promise.resolve().then(fn))(() => { _queueStatsCache = null; });
return _queueStatsCache;
}
@ -3691,7 +3691,10 @@ async function deleteAccount(accountId) {
// Fire-and-forget the persist. The earlier `await getConfig()` round-trip
// was redundant (we already have the truth in memory) and was the main
// source of perceived lag on add/delete.
window.api.saveConfig({ hosters: config.hosters }).catch(() => {});
window.api.saveConfig({ hosters: config.hosters }).catch((err) => {
if (window.api && window.api.debugLog) window.api.debugLog(`deleteAccount saveConfig failed: ${err && err.message ? err.message : err}`);
showCopyToast('Account-Löschung konnte nicht persistiert werden — bitte erneut versuchen.');
});
}
function readAccountCredsFromModal(authType) {
@ -3897,6 +3900,15 @@ async function _commitAccount(ctx, creds, validatedStatus, validatedMessage) {
const idx = config.hosters[ctx.hosterName].findIndex(a => a.id === accountId);
if (idx >= 0) {
config.hosters[ctx.hosterName][idx] = { ...config.hosters[ctx.hosterName][idx], ...creds };
} else {
_accountModalBusy = false;
const _sb = document.getElementById('saveAccountBtn'); if (_sb) _sb.disabled = false;
const _st = document.getElementById('accountModalStatus');
if (_st) {
_st.textContent = 'Account nicht mehr in der Config — wurde extern gelöscht. Modal schließen und neu anlegen.';
_st.className = 'account-modal-status error';
}
return;
}
} else {
accountId = `${ctx.hosterName}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
@ -4844,4 +4856,15 @@ function updateStatsPanel() {
}
// --- Start ---
init();
init().catch((err) => {
try {
if (window.api && window.api.debugLog) window.api.debugLog(`init failed: ${err && err.stack ? err.stack : err}`);
const root = document.getElementById('app') || document.body;
if (root) {
const banner = document.createElement('div');
banner.style.cssText = 'position:fixed;top:0;left:0;right:0;background:#5a1e1e;color:#fff;padding:8px;z-index:99999;font-family:sans-serif;font-size:13px';
banner.textContent = 'Initialisierung fehlgeschlagen: ' + (err && err.message ? err.message : err) + ' — bitte Diagnose-Paket exportieren oder Programm neu starten.';
root.appendChild(banner);
}
} catch {}
});