From 19e175c0635943c416ec2525661f0d6a7fa75877 Mon Sep 17 00:00:00 2001 From: Sam Haves Date: Mon, 6 Jul 2026 15:52:46 -0700 Subject: [PATCH] Fix MJZ decoder Windows path separator issue On Windows, std::filesystem::path::string() returns backslashes while zip entries use forward slashes. This caused lookup mismatches making MJZ decoding fail on Windows with 'could not decode content'. Use generic_string() (which always returns forward slashes) for all path operations used in zip entry lookups, and normalize the archive name at construction time. PiperOrigin-RevId: 943538265 Change-Id: I50cafff82fd7f5f315ccfc890f660e138e4448a2 --- src/xml/mjz/mjz_decoder.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/xml/mjz/mjz_decoder.cc b/src/xml/mjz/mjz_decoder.cc index f2bd64bb..eec6a5ba 100644 --- a/src/xml/mjz/mjz_decoder.cc +++ b/src/xml/mjz/mjz_decoder.cc @@ -61,7 +61,8 @@ class ZipArchiveProvider : public mjpResourceProvider { public: ZipArchiveProvider(std::string name, const void* buffer, int nbuffer, char* error, int error_sz) - : name_(std::move(name)), buffer_((char*)buffer, (char*)buffer + nbuffer) { + : name_(std::filesystem::path(name).generic_string()), + buffer_((char*)buffer, (char*)buffer + nbuffer) { mjp_defaultResourceProvider(this); std::memset(&archive_, 0, sizeof(archive_)); @@ -92,7 +93,8 @@ class ZipArchiveProvider : public mjpResourceProvider { const std::filesystem::path path(name_); root_model_ = (path / path.stem()).generic_string() + ".xml"; if (!Contains(root_model_)) { - root_model_ = (path / path.stem() / path.stem()).string() + ".xml"; + root_model_ = + (path / path.stem() / path.stem()).generic_string() + ".xml"; if (!Contains(root_model_)) { SetError(error, error_sz, "Zip error: no root XML file found."); return; @@ -111,13 +113,13 @@ class ZipArchiveProvider : public mjpResourceProvider { open = [](mjResource* resource) { ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider; auto path = std::filesystem::path(resource->name).lexically_normal(); - const bool found = self->Contains(path.string()); + const bool found = self->Contains(path.generic_string()); return found ? 1 : 0; }; read = [](mjResource* resource, const void** buffer) { ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider; auto path = std::filesystem::path(resource->name).lexically_normal(); - std::span bytes = self->Read(path.string()); + std::span bytes = self->Read(path.generic_string()); *buffer = bytes.data(); return static_cast(bytes.size()); };