diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 95f21da34..7c78c782d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -332,6 +332,7 @@ set(SLIC3R_TEST_SOURCES
${TESTDIR}/libslic3r/test_trianglemesh.cpp
${TESTDIR}/libslic3r/test_extrusion_entity.cpp
${TESTDIR}/libslic3r/test_3mf.cpp
+ ${TESTDIR}/libslic3r/test_amf.cpp
)
diff --git a/src/test/inputs/test_amf/5061-malicious.xml b/src/test/inputs/test_amf/5061-malicious.xml
new file mode 100644
index 000000000..9cde996f6
--- /dev/null
+++ b/src/test/inputs/test_amf/5061-malicious.xml
@@ -0,0 +1,20 @@
+
+
+ Split Pyramid
+ John Smith
+
+
+
+
diff --git a/src/test/inputs/test_amf/read-amf.xml b/src/test/inputs/test_amf/read-amf.xml
new file mode 100644
index 000000000..f366b2be4
--- /dev/null
+++ b/src/test/inputs/test_amf/read-amf.xml
@@ -0,0 +1,19 @@
+
+
+ Split Pyramid
+ John Smith
+
+
diff --git a/src/test/libslic3r/test_amf.cpp b/src/test/libslic3r/test_amf.cpp
new file mode 100644
index 000000000..dcd73946b
--- /dev/null
+++ b/src/test/libslic3r/test_amf.cpp
@@ -0,0 +1,28 @@
+#include
+#include
+#include "Model.hpp"
+#include "IO.hpp"
+
+
+using namespace Slic3r;
+
+SCENARIO("Reading AMF file") {
+ GIVEN("badly formed AMF file (missing vertices)") {
+ auto model {new Slic3r::Model()};
+ WHEN("AMF model is read") {
+ auto ret = Slic3r::IO::AMF::read(testfile("test_amf/5061-malicious.xml"),model);
+ THEN("read should return True") {
+ REQUIRE(ret);
+ }
+ }
+ }
+ GIVEN("Ok formed AMF file") {
+ auto model {new Slic3r::Model()};
+ WHEN("AMF model is read") {
+ auto ret = Slic3r::IO::AMF::read(testfile("test_amf/read-amf.xml"),model);
+ THEN("read should return True") {
+ REQUIRE(ret);
+ }
+ }
+ }
+}
diff --git a/xs/src/libslic3r/IO/AMF.cpp b/xs/src/libslic3r/IO/AMF.cpp
index e6eecfde4..a7c3cca7d 100644
--- a/xs/src/libslic3r/IO/AMF.cpp
+++ b/xs/src/libslic3r/IO/AMF.cpp
@@ -344,9 +344,13 @@ void AMFParserContext::endElement(const char *name)
// Faces of the current volume:
case NODE_TYPE_TRIANGLE:
assert(m_object && m_volume);
- m_volume_facets.push_back(atoi(m_value[0].c_str()));
- m_volume_facets.push_back(atoi(m_value[1].c_str()));
- m_volume_facets.push_back(atoi(m_value[2].c_str()));
+ if (strtoul(m_value[0].c_str(), nullptr, 10) < m_object_vertices.size() &&
+ strtoul(m_value[1].c_str(), nullptr, 10) < m_object_vertices.size() &&
+ strtoul(m_value[2].c_str(), nullptr, 10) < m_object_vertices.size()) {
+ m_volume_facets.push_back(atoi(m_value[0].c_str()));
+ m_volume_facets.push_back(atoi(m_value[1].c_str()));
+ m_volume_facets.push_back(atoi(m_value[2].c_str()));
+ }
m_value[0].clear();
m_value[1].clear();
m_value[2].clear();
@@ -363,8 +367,9 @@ void AMFParserContext::endElement(const char *name)
stl_allocate(&stl);
for (size_t i = 0; i < m_volume_facets.size();) {
stl_facet &facet = stl.facet_start[i/3];
- for (unsigned int v = 0; v < 3; ++ v)
+ for (unsigned int v = 0; v < 3; ++ v) {
memcpy(&facet.vertex[v].x, &m_object_vertices[m_volume_facets[i ++] * 3], 3 * sizeof(float));
+ }
}
stl_get_size(&stl);
m_volume->mesh.repair();