CVE-2021-44961: Slic3r libslic3r PerimeterGenerator Memory Leakage Vulnerability

4 minute read

Published:

CVE Number

CVE-2021-44961

Summary

A memory leakage flaw exists in the class PerimeterGenerator of Slic3r libslic3r 1.3.0 and Master Commit b1a5500. Specially crafted stl files can exhaust available memory. An attacker can provide malicious files to trigger this vulnerability.

Tested Versions

Slic3r libslic3r 1.3.0 Slic3r libslic3r Master Commit b1a5500

Product URLs

https://slic3r.org/

Details

When reading in an .stl file with the --export-gcode argument, class PerimeterGenerator is invoked. The class has some pointers to objects, but it does not provide a destructor and instead uses the default destructor. However, the default destructor only destroys the pointer, but not what the pointer was pointing to. Therefore, the allocated memories are not properly released upon the destruction of class PerimeterGenerator, leading to potential memory exhaustion.

class PerimeterGenerator {
public:
    // Inputs:
    const SurfaceCollection* slices;
    const ExPolygonCollection* lower_slices;
    double layer_height;
    int layer_id;
    Flow perimeter_flow;
    Flow ext_perimeter_flow;
    Flow overhang_flow;
    Flow solid_infill_flow;
    PrintRegionConfig* config;
    PrintObjectConfig* object_config;
    PrintConfig* print_config;
    // Outputs:
    ExtrusionEntityCollection* loops;
    ExtrusionEntityCollection* gap_fill;
    SurfaceCollection* fill_surfaces;
    
    PerimeterGenerator(
        // Input:
        const SurfaceCollection*    slices, 
        double                      layer_height,
        Flow                        flow,
        PrintRegionConfig*          config,
        PrintObjectConfig*          object_config,
        PrintConfig*                print_config,
        // Output:
        // Loops with the external thin walls
        ExtrusionEntityCollection*  loops,
        // Gaps without the thin walls
        ExtrusionEntityCollection*  gap_fill,
        // Infills without the gap fills
        SurfaceCollection*          fill_surfaces)
        : slices(slices), lower_slices(NULL), layer_height(layer_height),
            layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow),
            overhang_flow(flow), solid_infill_flow(flow),
            config(config), object_config(object_config), print_config(print_config),
            loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces),
            _ext_mm3_per_mm(-1), _mm3_per_mm(-1), _mm3_per_mm_overhang(-1)
        {};
    void process();
    
    private:
    double _ext_mm3_per_mm;
    double _mm3_per_mm;
    double _mm3_per_mm_overhang;
    Polygons _lower_slices_p;
    
    ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops,
        ThickPolylines &thin_walls) const;
    ExtrusionEntityCollection _variable_width
        (const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const;
};

}

Crash Information

Direct leak of 19456 byte(s) in 304 object(s) allocated from:
#0 0x55dca2 in operator new(unsigned long) (/home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/build/slic3r+0x55dca2)
#1 0xe9ef4d in Slic3r::ExtrusionPath::clone() const /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/src/../xs/src/libslic3r/ExtrusionEntity.hpp:77:43
#2 0x69c402 in Slic3r::ExtrusionEntityCollection::append(Slic3r::ExtrusionEntity const&) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:94:37
#3 0x6985fa in Slic3r::ExtrusionEntityCollection::append(std::vector<Slic3r::ExtrusionEntity*, std::allocator<Slic3r::ExtrusionEntity*> > const&) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:101:15
#4 0x697dc8 in Slic3r::ExtrusionEntityCollection::ExtrusionEntityCollection(Slic3r::ExtrusionEntityCollection const&) Direct leak of 19456 byte(s) in 304 object(s) allocated from:
#0 0x55dca2 in operator new(unsigned long) (/home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/build/slic3r+0x55dca2)
#1 0xe9ef4d in Slic3r::ExtrusionPath::clone() const /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/src/../xs/src/libslic3r/ExtrusionEntity.hpp:77:43
#2 0x69c402 in Slic3r::ExtrusionEntityCollection::append(Slic3r::ExtrusionEntity const&) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:94:37
#3 0x6985fa in Slic3r::ExtrusionEntityCollection::append(std::vector<Slic3r::ExtrusionEntity*, std::allocator<Slic3r::ExtrusionEntity*> > const&) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:101:15
#4 0x697dc8 in Slic3r::ExtrusionEntityCollection::ExtrusionEntityCollection(Slic3r::ExtrusionEntityCollection const&) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:11:11
#5 0x69ad9c in Slic3r::ExtrusionEntityCollection::clone() const /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:61:43
#6 0x69c402 in Slic3r::ExtrusionEntityCollection::append(Slic3r::ExtrusionEntity const&) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:94:37
#7 0x1030a22 in Slic3r::PerimeterGenerator::process() /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/PerimeterGenerator.cpp:274:30
#8 0xfe5efd in Slic3r::LayerRegion::make_perimeters(Slic3r::SurfaceCollection const&, Slic3r::SurfaceCollection*) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/LayerRegion.cpp:70:7
#9 0xfd6d81 in Slic3r::Layer::make_perimeters() /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/Layer.cpp:201:24
#10 0xaebb2b in boost::_mfi::mf0<void, Slic3r::Layer>::operator()(Slic3r::Layer*) const /usr/include/boost/bind/mem_fn_template.hpp:49:29
#11 0xaeb921 in void boost::_bi::list1<boost::arg<1> >::operator()<boost::_mfi::mf0<void, Slic3r::Layer>, boost::_bi::list1<Slic3r::Layer* const&> >(boost::_bi::type<void>, boost::_mfi::mf0<void, Slic3r::Layer>&, boost::_bi::list1<Slic3r::Layer* const&>&, int) /usr/include/boost/bind/bind.hpp:253:9
#12 0xaeb796 in void boost::_bi::bind_t<void, boost::_mfi::mf0<void, Slic3r::Layer>, boost::_bi::list1<boost::arg<1> > >::operator()<Slic3r::Layer*>(Slic3r::Layer*&&) /usr/include/boost/bind/bind.hpp:905:16
#13 0xaeaed4 in boost::detail::function::void_function_obj_invoker1<boost::_bi::bind_t<void, boost::_mfi::mf0<void, Slic3r::Layer>, boost::_bi::list1<boost::arg<1> > >, void, Slic3r::Layer*>::invoke(boost::detail::function::function_buffer&, Slic3r::Layer*) /usr/include/boost/function/function_template.hpp:159:11
#14 0xae54fe in boost::function1<void, Slic3r::Layer*>::operator()(Slic3r::Layer*) const /usr/include/boost/function/function_template.hpp:772:14
#15 0xaddf94 in void Slic3r::_parallelize_do<Slic3r::Layer*>(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/src/../xs/src/libslic3r/Fill/../libslic3r.h:119:9
#16 0xae7383 in void boost::_bi::list3<boost::_bi::value<std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*>, boost::_bi::value<boost::mutex*>, boost::_bi::value<boost::function<void (Slic3r::Layer*)> > >::operator()<void (*)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list0>(boost::_bi::type<void>, void (*&)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list0&, int) /usr/include/boost/bind/bind.hpp:392:9
#17 0xae70d6 in boost::_bi::bind_t<void, void (*)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list3<boost::_bi::value<std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*>, boost::_bi::value<boost::mutex*>, boost::_bi::value<boost::function<void (Slic3r::Layer*)> > > >::operator()() /usr/include/boost/bind/bind.hpp:893:16
#18 0xae69be in boost::detail::thread_data<boost::_bi::bind_t<void, void (*)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list3<boost::_bi::value<std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*>, boost::_bi::value<boost::mutex*>, boost::_bi::value<boost::function<void (Slic3r::Layer*)> > > > >::run() /usr/include/boost/thread/detail/thread.hpp:116:17
#19 0x1c8b334 in thread_proxy (/home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/build/slic3r+0x1c8b334)/home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:11:11
#5 0x69ad9c in Slic3r::ExtrusionEntityCollection::clone() const /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:61:43
#6 0x69c402 in Slic3r::ExtrusionEntityCollection::append(Slic3r::ExtrusionEntity const&) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/ExtrusionEntityCollection.cpp:94:37
#7 0x1030a22 in Slic3r::PerimeterGenerator::process() /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/PerimeterGenerator.cpp:274:30
#8 0xfe5efd in Slic3r::LayerRegion::make_perimeters(Slic3r::SurfaceCollection const&, Slic3r::SurfaceCollection*) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/LayerRegion.cpp:70:7
#9 0xfd6d81 in Slic3r::Layer::make_perimeters() /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/xs/src/libslic3r/Layer.cpp:201:24
#10 0xaebb2b in boost::_mfi::mf0<void, Slic3r::Layer>::operator()(Slic3r::Layer*) const /usr/include/boost/bind/mem_fn_template.hpp:49:29
#11 0xaeb921 in void boost::_bi::list1<boost::arg<1> >::operator()<boost::_mfi::mf0<void, Slic3r::Layer>, boost::_bi::list1<Slic3r::Layer* const&> >(boost::_bi::type<void>, boost::_mfi::mf0<void, Slic3r::Layer>&, boost::_bi::list1<Slic3r::Layer* const&>&, int) /usr/include/boost/bind/bind.hpp:253:9
#12 0xaeb796 in void boost::_bi::bind_t<void, boost::_mfi::mf0<void, Slic3r::Layer>, boost::_bi::list1<boost::arg<1> > >::operator()<Slic3r::Layer*>(Slic3r::Layer*&&) /usr/include/boost/bind/bind.hpp:905:16
#13 0xaeaed4 in boost::detail::function::void_function_obj_invoker1<boost::_bi::bind_t<void, boost::_mfi::mf0<void, Slic3r::Layer>, boost::_bi::list1<boost::arg<1> > >, void, Slic3r::Layer*>::invoke(boost::detail::function::function_buffer&, Slic3r::Layer*) /usr/include/boost/function/function_template.hpp:159:11
#14 0xae54fe in boost::function1<void, Slic3r::Layer*>::operator()(Slic3r::Layer*) const /usr/include/boost/function/function_template.hpp:772:14
#15 0xaddf94 in void Slic3r::_parallelize_do<Slic3r::Layer*>(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>) /home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/src/../xs/src/libslic3r/Fill/../libslic3r.h:119:9
#16 0xae7383 in void boost::_bi::list3<boost::_bi::value<std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*>, boost::_bi::value<boost::mutex*>, boost::_bi::value<boost::function<void (Slic3r::Layer*)> > >::operator()<void (*)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list0>(boost::_bi::type<void>, void (*&)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list0&, int) /usr/include/boost/bind/bind.hpp:392:9
#17 0xae70d6 in boost::_bi::bind_t<void, void (*)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list3<boost::_bi::value<std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*>, boost::_bi::value<boost::mutex*>, boost::_bi::value<boost::function<void (Slic3r::Layer*)> > > >::operator()() /usr/include/boost/bind/bind.hpp:893:16
#18 0xae69be in boost::detail::thread_data<boost::_bi::bind_t<void, void (*)(std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*, boost::mutex*, boost::function<void (Slic3r::Layer*)>), boost::_bi::list3<boost::_bi::value<std::queue<Slic3r::Layer*, std::deque<Slic3r::Layer*, std::allocator<Slic3r::Layer*> > >*>, boost::_bi::value<boost::mutex*>, boost::_bi::value<boost::function<void (Slic3r::Layer*)> > > > >::run() /usr/include/boost/thread/detail/thread.hpp:116:17
#19 0x1c8b334 in thread_proxy (/home/bug/LabSpace/ins_FuzzerRun/Slic3rFuzzer/build/slic3r+0x1c8b334)

Timeline

2021-11-19 - Vendor Disclosure
2022-01-16 - Public Release

Credit

Discovered by Yuanhaur Chang, Yujie Wang, and Ning Zhang