Lexically normalize resource path in mjz_decoder resource provider.

PiperOrigin-RevId: 922654438
Change-Id: Ieb46230a2aba46a5e711bc5b24aec982f71e56ca
This commit is contained in:
Sam Haves
2026-05-28 02:56:01 -07:00
committed by Copybara-Service
parent f755d718d3
commit b9fb817af8
2 changed files with 18 additions and 3 deletions
+8
View File
@@ -2,6 +2,14 @@
Changelog
=========
Upcoming version (not yet released)
-----------------------------------
Bug fixes
^^^^^^^^^
- Fixed a bug in the ``mjz`` :ref:`decoder <mjpDecoder>` where unnormalized paths would fail to be read.
Version 3.9.0 (May 27, 2026)
----------------------------
+10 -3
View File
@@ -90,7 +90,7 @@ class ZipArchiveProvider : public mjpResourceProvider {
// with the same name as the archive itself. Failing that, look for an XML
// file within a subdirectory with the same name as the archive.
const std::filesystem::path path(name_);
root_model_ = (path / path.stem()).string() + ".xml";
root_model_ = (path / path.stem()).generic_string() + ".xml";
if (!Contains(root_model_)) {
root_model_ = (path / path.stem() / path.stem()).string() + ".xml";
if (!Contains(root_model_)) {
@@ -110,12 +110,14 @@ class ZipArchiveProvider : public mjpResourceProvider {
};
open = [](mjResource* resource) {
ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider;
const bool found = self->Contains(resource->name);
auto path = std::filesystem::path(resource->name).lexically_normal();
const bool found = self->Contains(path.string());
return found ? 1 : 0;
};
read = [](mjResource* resource, const void** buffer) {
ZipArchiveProvider* self = (ZipArchiveProvider*)resource->provider;
std::span<char> bytes = self->Read(resource->name);
auto path = std::filesystem::path(resource->name).lexically_normal();
std::span<char> bytes = self->Read(path.string());
*buffer = bytes.data();
return static_cast<int>(bytes.size());
};
@@ -138,6 +140,11 @@ class ZipArchiveProvider : public mjpResourceProvider {
// Returns true if the archive contains a file with the given name/path.
bool Contains(std::string_view name) const {
// Lexically normalized path might strip the archive path.
// a/b.mjz/../../../c.xml -> ../c.xml
if (!name.starts_with(name_)) {
return false;
}
const std::string_view filename = name.substr(name_.size() + 1);
return files_.find(filename.data()) != files_.end();
}