From 1f529bd61016de07501ef7819c51141fe40b8d8a Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 23 May 2024 12:26:25 -0300 Subject: [PATCH] Fix a couple of bugs restoring backup sessions With https://community.aseprite.org/t/layers-become-empty-when-autosaving/22141 we found a couple of bugs where only 2 backed up versions of stored objects were added in ObjVersions::add(). Also as ObjVersions has a limited space for 3 versions, it's a good idea to ignore invalid binary files (files without the magic number "FINE" as header). So now we only add valid versions to ObjVersions, previously we could lead to a situation where 3 invalid binary versions of the same object were added to the ObjVersions and a 4th valid version were ignored. Related to: https://github.com/aseprite/aseprite/issues/4481 --- src/app/crash/internals.h | 5 +++-- src/app/crash/read_document.cpp | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/app/crash/internals.h b/src/app/crash/internals.h index 77f3f029f..8ca8176a3 100644 --- a/src/app/crash/internals.h +++ b/src/app/crash/internals.h @@ -1,4 +1,5 @@ // Aseprite +// Copyright (C) 2024 Igara Studio S.A. // Copyright (C) 2001-2015 David Capello // // This program is distributed under the terms of @@ -43,10 +44,10 @@ namespace crash { // Adds a version (we don't know if the version if the latest one) void add(doc::ObjectVersion ver) { - auto minver = std::min_element(m_vers, m_vers+2); + auto* minver = std::min_element(m_vers, m_vers+size()); if (*minver < ver) { *minver = ver; - std::sort(m_vers, m_vers+2, std::greater()); + std::sort(m_vers, m_vers+size(), std::greater()); } } diff --git a/src/app/crash/read_document.cpp b/src/app/crash/read_document.cpp index ec2ce2d4b..73a79e637 100644 --- a/src/app/crash/read_document.cpp +++ b/src/app/crash/read_document.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2023 Igara Studio S.A. +// Copyright (C) 2018-2024 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -58,6 +58,14 @@ using namespace doc; namespace { +// Returns true if the file was saved correctly (has the "FINE" magic +// number), so we can ignore broken versions of objects directly. +bool check_magic_number(const std::string& fn) +{ + std::ifstream s(FSTREAM_PATH(fn), std::ifstream::binary); + return (read32(s) == MAGIC_NUMBER); +} + class Reader : public SubObjectsIO { public: Reader(const std::string& dir, @@ -83,6 +91,11 @@ public: if (!id || !ver) continue; // Error converting strings to ID/ver + if (!check_magic_number(base::join_path(m_dir, fn))) { + RECO_TRACE("RECO: Ignoring invalid file %s (no magic number)\n", fn.c_str()); + continue; + } + ObjVersions& versions = m_objVersions[id]; versions.add(ver);