diff --git a/base/nix/mime_util_xdg.cc b/base/nix/mime_util_xdg.cc index 36396fd666d25..9bdb487e7e33a 100644 --- a/base/nix/mime_util_xdg.cc +++ b/base/nix/mime_util_xdg.cc @@ -259,22 +259,25 @@ std::string GetFileMimeType(const FilePath& filepath) { static Time last_check; // Lock is required since this may be called on any thread. static NoDestructor lock; - { - AutoLock scoped_lock(*lock); + // The lock must be held through the find() and the iterator dereference + // below: another thread can otherwise call clear() (under this lock) while + // we hold a raw _Rb_tree_node pointer, freeing the node we're about to read. + // See crbug.com/####. The std::string copy on the return line allocates a + // fresh buffer, so it is safe to release the lock immediately after. + AutoLock scoped_lock(*lock); - Time now = Time::Now(); - if (last_check + Seconds(5) < now) { - if (std::ranges::any_of(*xdg_mime_files, [](const FileInfo& file_info) { - File::Info info; - return !GetFileInfo(file_info.path, &info) || - info.last_modified != file_info.last_modified; - })) { - mime_type_map->clear(); - xdg_mime_files->clear(); - LoadAllMimeCacheFiles(*mime_type_map, *xdg_mime_files); - } - last_check = now; + Time now = Time::Now(); + if (last_check + Seconds(5) < now) { + if (std::ranges::any_of(*xdg_mime_files, [](const FileInfo& file_info) { + File::Info info; + return !GetFileInfo(file_info.path, &info) || + info.last_modified != file_info.last_modified; + })) { + mime_type_map->clear(); + xdg_mime_files->clear(); + LoadAllMimeCacheFiles(*mime_type_map, *xdg_mime_files); } + last_check = now; } #endif