Make GfxColorSpace::parse and friends return unique_ptr
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 4fac308..08f695e 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -16,7 +16,7 @@
 //
 // Copyright (C) 2005-2008 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright (C) 2005, 2006 Kristian Høgsberg <krh@redhat.com>
-// Copyright (C) 2005, 2009, 2012, 2017-2021, 2023 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005, 2009, 2012, 2017-2021, 2023, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2005 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
 // Copyright (C) 2006-2011, 2013, 2014, 2017, 2018 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2008 Carl Worth <cworth@cworth.org>
@@ -3188,7 +3188,6 @@
     char *strBuffer;
     int len;
     Object obj;
-    GfxColorSpace *colorSpace;
     StreamKind strKind = str->getKind();
     const char *mime_type;
     cairo_status_t status;
@@ -3228,7 +3227,7 @@
     }
 
     obj = str->getDict()->lookup("ColorSpace");
-    colorSpace = GfxColorSpace::parse(nullptr, &obj, this, state);
+    std::unique_ptr<GfxColorSpace> colorSpace = GfxColorSpace::parse(nullptr, &obj, this, state);
 
     // colorspace in stream dict may be different from colorspace in jpx
     // data
@@ -3239,7 +3238,6 @@
     // only embed mime data for gray, rgb, and cmyk colorspaces.
     if (colorSpace) {
         GfxColorSpaceMode mode = colorSpace->getMode();
-        delete colorSpace;
         switch (mode) {
         case csDeviceGray:
         case csCalGray:
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index d8dd533..539fa4d 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
-// Copyright (C) 2005-2013, 2015-2022 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005-2013, 2015-2022, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006 Thorkild Stray <thorkild@ifi.uio.no>
 // Copyright (C) 2006 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2006-2011 Carlos Garcia Campos <carlosgc@gnome.org>
@@ -1143,7 +1143,7 @@
             if (obj3.isStream()) {
                 Object obj4 = obj3.streamGetDict()->lookup("Group");
                 if (obj4.isDict()) {
-                    GfxColorSpace *blendingColorSpace = nullptr;
+                    std::unique_ptr<GfxColorSpace> blendingColorSpace;
                     Object obj5 = obj4.dictLookup("CS");
                     if (!obj5.isNull()) {
                         blendingColorSpace = GfxColorSpace::parse(res, &obj5, out, state);
@@ -1160,8 +1160,7 @@
                             }
                         }
                     }
-                    doSoftMask(&obj3, alpha, blendingColorSpace, isolated, knockout, softMaskTransferFunc, &backdropColor);
-                    delete blendingColorSpace;
+                    doSoftMask(&obj3, alpha, blendingColorSpace.get(), isolated, knockout, softMaskTransferFunc, &backdropColor);
                 } else {
                     error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState - missing group");
                 }
@@ -1303,18 +1302,17 @@
 void Gfx::opSetFillGray(Object args[], int numArgs)
 {
     GfxColor color;
-    GfxColorSpace *colorSpace = nullptr;
+    std::unique_ptr<GfxColorSpace> colorSpace;
 
     state->setFillPattern(nullptr);
     Object obj = res->lookupColorSpace("DefaultGray");
     if (!obj.isNull()) {
         colorSpace = GfxColorSpace::parse(res, &obj, out, state);
     }
-    if (colorSpace == nullptr || colorSpace->getNComps() > 1) {
-        delete colorSpace;
+    if (!colorSpace || colorSpace->getNComps() > 1) {
         colorSpace = state->copyDefaultGrayColorSpace();
     }
-    state->setFillColorSpace(colorSpace);
+    state->setFillColorSpace(std::move(colorSpace));
     out->updateFillColorSpace(state);
     color.c[0] = dblToCol(args[0].getNum());
     state->setFillColor(&color);
@@ -1324,17 +1322,17 @@
 void Gfx::opSetStrokeGray(Object args[], int numArgs)
 {
     GfxColor color;
-    GfxColorSpace *colorSpace = nullptr;
+    std::unique_ptr<GfxColorSpace> colorSpace;
 
     state->setStrokePattern(nullptr);
     Object obj = res->lookupColorSpace("DefaultGray");
     if (!obj.isNull()) {
         colorSpace = GfxColorSpace::parse(res, &obj, out, state);
     }
-    if (colorSpace == nullptr) {
+    if (!colorSpace) {
         colorSpace = state->copyDefaultGrayColorSpace();
     }
-    state->setStrokeColorSpace(colorSpace);
+    state->setStrokeColorSpace(std::move(colorSpace));
     out->updateStrokeColorSpace(state);
     color.c[0] = dblToCol(args[0].getNum());
     state->setStrokeColor(&color);
@@ -1344,18 +1342,18 @@
 void Gfx::opSetFillCMYKColor(Object args[], int numArgs)
 {
     GfxColor color;
-    GfxColorSpace *colorSpace = nullptr;
+    std::unique_ptr<GfxColorSpace> colorSpace;
     int i;
 
     Object obj = res->lookupColorSpace("DefaultCMYK");
     if (!obj.isNull()) {
         colorSpace = GfxColorSpace::parse(res, &obj, out, state);
     }
-    if (colorSpace == nullptr) {
+    if (!colorSpace) {
         colorSpace = state->copyDefaultCMYKColorSpace();
     }
     state->setFillPattern(nullptr);
-    state->setFillColorSpace(colorSpace);
+    state->setFillColorSpace(std::move(colorSpace));
     out->updateFillColorSpace(state);
     for (i = 0; i < 4; ++i) {
         color.c[i] = dblToCol(args[i].getNum());
@@ -1367,7 +1365,7 @@
 void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs)
 {
     GfxColor color;
-    GfxColorSpace *colorSpace = nullptr;
+    std::unique_ptr<GfxColorSpace> colorSpace;
     int i;
 
     state->setStrokePattern(nullptr);
@@ -1375,10 +1373,10 @@
     if (!obj.isNull()) {
         colorSpace = GfxColorSpace::parse(res, &obj, out, state);
     }
-    if (colorSpace == nullptr) {
+    if (!colorSpace) {
         colorSpace = state->copyDefaultCMYKColorSpace();
     }
-    state->setStrokeColorSpace(colorSpace);
+    state->setStrokeColorSpace(std::move(colorSpace));
     out->updateStrokeColorSpace(state);
     for (i = 0; i < 4; ++i) {
         color.c[i] = dblToCol(args[i].getNum());
@@ -1389,7 +1387,7 @@
 
 void Gfx::opSetFillRGBColor(Object args[], int numArgs)
 {
-    GfxColorSpace *colorSpace = nullptr;
+    std::unique_ptr<GfxColorSpace> colorSpace;
     GfxColor color;
     int i;
 
@@ -1398,11 +1396,10 @@
     if (!obj.isNull()) {
         colorSpace = GfxColorSpace::parse(res, &obj, out, state);
     }
-    if (colorSpace == nullptr || colorSpace->getNComps() > 3) {
-        delete colorSpace;
+    if (!colorSpace || colorSpace->getNComps() > 3) {
         colorSpace = state->copyDefaultRGBColorSpace();
     }
-    state->setFillColorSpace(colorSpace);
+    state->setFillColorSpace(std::move(colorSpace));
     out->updateFillColorSpace(state);
     for (i = 0; i < 3; ++i) {
         color.c[i] = dblToCol(args[i].getNum());
@@ -1413,7 +1410,7 @@
 
 void Gfx::opSetStrokeRGBColor(Object args[], int numArgs)
 {
-    GfxColorSpace *colorSpace = nullptr;
+    std::unique_ptr<GfxColorSpace> colorSpace;
     GfxColor color;
     int i;
 
@@ -1422,10 +1419,10 @@
     if (!obj.isNull()) {
         colorSpace = GfxColorSpace::parse(res, &obj, out, state);
     }
-    if (colorSpace == nullptr) {
+    if (!colorSpace) {
         colorSpace = state->copyDefaultRGBColorSpace();
     }
-    state->setStrokeColorSpace(colorSpace);
+    state->setStrokeColorSpace(std::move(colorSpace));
     out->updateStrokeColorSpace(state);
     for (i = 0; i < 3; ++i) {
         color.c[i] = dblToCol(args[i].getNum());
@@ -1436,7 +1433,7 @@
 
 void Gfx::opSetFillColorSpace(Object args[], int numArgs)
 {
-    GfxColorSpace *colorSpace;
+    std::unique_ptr<GfxColorSpace> colorSpace;
     GfxColor color;
 
     Object obj = res->lookupColorSpace(args[0].getName());
@@ -1447,9 +1444,9 @@
     }
     if (colorSpace) {
         state->setFillPattern(nullptr);
-        state->setFillColorSpace(colorSpace);
+        state->setFillColorSpace(std::move(colorSpace));
         out->updateFillColorSpace(state);
-        colorSpace->getDefaultColor(&color);
+        state->getFillColorSpace()->getDefaultColor(&color);
         state->setFillColor(&color);
         out->updateFillColor(state);
     } else {
@@ -1459,7 +1456,7 @@
 
 void Gfx::opSetStrokeColorSpace(Object args[], int numArgs)
 {
-    GfxColorSpace *colorSpace;
+    std::unique_ptr<GfxColorSpace> colorSpace;
     GfxColor color;
 
     state->setStrokePattern(nullptr);
@@ -1470,9 +1467,9 @@
         colorSpace = GfxColorSpace::parse(res, &obj, out, state);
     }
     if (colorSpace) {
-        state->setStrokeColorSpace(colorSpace);
+        state->setStrokeColorSpace(std::move(colorSpace));
         out->updateStrokeColorSpace(state);
-        colorSpace->getDefaultColor(&color);
+        state->getStrokeColorSpace()->getDefaultColor(&color);
         state->setStrokeColor(&color);
         out->updateStrokeColor(state);
     } else {
@@ -1979,7 +1976,6 @@
 void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, bool stroke, bool eoFill, bool text)
 {
     GfxPatternColorSpace *patCS;
-    GfxColorSpace *cs;
     GfxColor color;
     GfxState *savedState;
     double xMin, yMin, xMax, yMax, x, y, x1, y1;
@@ -2048,7 +2044,8 @@
     // Adobe's behavior
     state->setFillPattern(nullptr);
     state->setStrokePattern(nullptr);
-    if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
+    if (tPat->getPaintType() == 2 && patCS->getUnder()) {
+        GfxColorSpace *cs = patCS->getUnder();
         state->setFillColorSpace(cs->copy());
         out->updateFillColorSpace(state);
         state->setStrokeColorSpace(cs->copy());
@@ -2061,12 +2058,11 @@
         out->updateFillColor(state);
         out->updateStrokeColor(state);
     } else {
-        cs = new GfxDeviceGrayColorSpace();
-        state->setFillColorSpace(cs);
-        cs->getDefaultColor(&color);
+        state->setFillColorSpace(std::make_unique<GfxDeviceGrayColorSpace>());
+        state->getFillColorSpace()->getDefaultColor(&color);
         state->setFillColor(&color);
         out->updateFillColorSpace(state);
-        state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
+        state->setStrokeColorSpace(std::make_unique<GfxDeviceGrayColorSpace>());
         state->setStrokeColor(&color);
         out->updateStrokeColorSpace(state);
     }
@@ -4169,7 +4165,6 @@
     StreamColorSpaceMode csMode;
     bool mask;
     bool invert;
-    GfxColorSpace *colorSpace, *maskColorSpace;
     bool haveColorKeyMask, haveExplicitMask, haveSoftMask;
     int maskColors[2 * gfxColorMaxComps] = {};
     int maskWidth, maskHeight;
@@ -4323,6 +4318,8 @@
                 obj1 = std::move(obj2);
             }
         }
+        std::unique_ptr<GfxColorSpace> colorSpace;
+
         if (!obj1.isNull()) {
             char *tempIntent = nullptr;
             Object objIntent = dict->lookup("Intent");
@@ -4341,26 +4338,24 @@
         } else if (csMode == streamCSDeviceGray) {
             Object objCS = res->lookupColorSpace("DefaultGray");
             if (objCS.isNull()) {
-                colorSpace = new GfxDeviceGrayColorSpace();
+                colorSpace = std::make_unique<GfxDeviceGrayColorSpace>();
             } else {
                 colorSpace = GfxColorSpace::parse(res, &objCS, out, state);
             }
         } else if (csMode == streamCSDeviceRGB) {
             Object objCS = res->lookupColorSpace("DefaultRGB");
             if (objCS.isNull()) {
-                colorSpace = new GfxDeviceRGBColorSpace();
+                colorSpace = std::make_unique<GfxDeviceRGBColorSpace>();
             } else {
                 colorSpace = GfxColorSpace::parse(res, &objCS, out, state);
             }
         } else if (csMode == streamCSDeviceCMYK) {
             Object objCS = res->lookupColorSpace("DefaultCMYK");
             if (objCS.isNull()) {
-                colorSpace = new GfxDeviceCMYKColorSpace();
+                colorSpace = std::make_unique<GfxDeviceCMYKColorSpace>();
             } else {
                 colorSpace = GfxColorSpace::parse(res, &objCS, out, state);
             }
-        } else {
-            colorSpace = nullptr;
         }
         if (!colorSpace) {
             goto err1;
@@ -4369,7 +4364,7 @@
         if (obj1.isNull()) {
             obj1 = dict->lookup("D");
         }
-        GfxImageColorMap colorMap(bits, &obj1, colorSpace);
+        GfxImageColorMap colorMap(bits, &obj1, std::move(colorSpace));
         if (!colorMap.isOk()) {
             goto err1;
         }
@@ -4467,25 +4462,24 @@
             if (!obj1.isName("DeviceGray") && !obj1.isName("G")) {
                 goto err1;
             }
-            maskColorSpace = new GfxDeviceGrayColorSpace();
             obj1 = maskDict->lookup("Decode");
             if (obj1.isNull()) {
                 obj1 = maskDict->lookup("D");
             }
-            maskColorMap = std::make_unique<GfxImageColorMap>(maskBits, &obj1, maskColorSpace);
+            maskColorMap = std::make_unique<GfxImageColorMap>(maskBits, &obj1, std::make_unique<GfxDeviceGrayColorSpace>());
             if (!maskColorMap->isOk()) {
                 goto err1;
             }
             // handle the Matte entry
             obj1 = maskDict->lookup("Matte");
             if (obj1.isArray()) {
-                if (obj1.getArray()->getLength() != colorSpace->getNComps()) {
-                    error(errSyntaxError, -1, "Matte entry should have {0:d} components but has {1:d}", colorSpace->getNComps(), obj1.getArray()->getLength());
+                if (obj1.getArray()->getLength() != colorMap.getColorSpace()->getNComps()) {
+                    error(errSyntaxError, -1, "Matte entry should have {0:d} components but has {1:d}", colorMap.getColorSpace()->getNComps(), obj1.getArray()->getLength());
                 } else if (maskWidth != width || maskHeight != height) {
                     error(errSyntaxError, -1, "Softmask with matte entry {0:d} x {1:d} must have same geometry as the image {2:d} x {3:d}", maskWidth, maskHeight, width, height);
                 } else {
                     GfxColor matteColor;
-                    for (i = 0; i < colorSpace->getNComps(); i++) {
+                    for (i = 0; i < colorMap.getColorSpace()->getNComps(); i++) {
                         Object obj2 = obj1.getArray()->get(i);
                         if (!obj2.isNum()) {
                             error(errSyntaxError, -1, "Matte entry {0:d} should be a number but it's of type {1:d}", i, obj2.getType());
@@ -4494,7 +4488,7 @@
                         }
                         matteColor.c[i] = dblToCol(obj2.getNum());
                     }
-                    if (i == colorSpace->getNComps()) {
+                    if (i == colorMap.getColorSpace()->getNComps()) {
                         maskColorMap->setMatteColor(&matteColor);
                     }
                 }
@@ -4678,7 +4672,6 @@
 {
     Dict *dict;
     bool transpGroup, isolated, knockout;
-    GfxColorSpace *blendingColorSpace;
     double m[6], bbox[4];
     Dict *resDict;
     bool ocSaved;
@@ -4748,7 +4741,7 @@
 
     // check for a transparency group
     transpGroup = isolated = knockout = false;
-    blendingColorSpace = nullptr;
+    std::unique_ptr<GfxColorSpace> blendingColorSpace;
     obj1 = dict->lookup("Group");
     if (obj1.isDict()) {
         Object obj2 = obj1.dictLookup("S");
@@ -4770,11 +4763,7 @@
     }
 
     // draw it
-    drawForm(str, resDict, m, bbox, transpGroup, false, blendingColorSpace, isolated, knockout);
-
-    if (blendingColorSpace) {
-        delete blendingColorSpace;
-    }
+    drawForm(str, resDict, m, bbox, transpGroup, false, blendingColorSpace.get(), isolated, knockout);
 
     ocState = ocSaved;
 }
@@ -5306,7 +5295,7 @@
     if (border && border->getWidth() > 0 && (!aColor || aColor->getSpace() != AnnotColor::colorTransparent)) {
         if (state->getStrokeColorSpace()->getMode() != csDeviceRGB) {
             state->setStrokePattern(nullptr);
-            state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
+            state->setStrokeColorSpace(std::make_unique<GfxDeviceRGBColorSpace>());
             out->updateStrokeColorSpace(state);
         }
         double r, g, b;
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index cbb3fea..91544d9 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -16,7 +16,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2006, 2007 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright (C) 2006, 2010 Carlos Garcia Campos <carlosgc@gnome.org>
-// Copyright (C) 2006-2022 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2006-2022, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2009, 2012 Koji Otani <sho@bbr.jp>
 // Copyright (C) 2009, 2011-2016, 2020, 2023 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2009, 2019 Christian Persch <chpe@gnome.org>
@@ -219,53 +219,51 @@
 
 GfxColorSpace::~GfxColorSpace() { }
 
-GfxColorSpace *GfxColorSpace::parse(GfxResources *res, Object *csObj, OutputDev *out, GfxState *state, int recursion)
+std::unique_ptr<GfxColorSpace> GfxColorSpace::parse(GfxResources *res, Object *csObj, OutputDev *out, GfxState *state, int recursion)
 {
-    GfxColorSpace *cs;
     Object obj1;
 
     if (recursion > colorSpaceRecursionLimit) {
         error(errSyntaxError, -1, "Loop detected in color space objects");
-        return nullptr;
+        return {};
     }
 
-    cs = nullptr;
     if (csObj->isName()) {
         if (csObj->isName("DeviceGray") || csObj->isName("G")) {
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultGray");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultGrayColorSpace();
+                    return state->copyDefaultGrayColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultGrayColorSpace();
+                return state->copyDefaultGrayColorSpace();
             }
         } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultRGB");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultRGBColorSpace();
+                    return state->copyDefaultRGBColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultRGBColorSpace();
+                return state->copyDefaultRGBColorSpace();
             }
         } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultCMYK");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultCMYKColorSpace();
+                    return state->copyDefaultCMYKColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultCMYKColorSpace();
+                return state->copyDefaultCMYKColorSpace();
             }
         } else if (csObj->isName("Pattern")) {
-            cs = new GfxPatternColorSpace(nullptr);
+            return std::make_unique<GfxPatternColorSpace>(nullptr);
         } else {
             error(errSyntaxWarning, -1, "Bad color space '{0:s}'", csObj->getName());
         }
@@ -275,51 +273,51 @@
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultGray");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultGrayColorSpace();
+                    return state->copyDefaultGrayColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultGrayColorSpace();
+                return state->copyDefaultGrayColorSpace();
             }
         } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultRGB");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultRGBColorSpace();
+                    return state->copyDefaultRGBColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultRGBColorSpace();
+                return state->copyDefaultRGBColorSpace();
             }
         } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultCMYK");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultCMYKColorSpace();
+                    return state->copyDefaultCMYKColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultCMYKColorSpace();
+                return state->copyDefaultCMYKColorSpace();
             }
         } else if (obj1.isName("CalGray")) {
-            cs = GfxCalGrayColorSpace::parse(csObj->getArray(), state);
+            return GfxCalGrayColorSpace::parse(csObj->getArray(), state);
         } else if (obj1.isName("CalRGB")) {
-            cs = GfxCalRGBColorSpace::parse(csObj->getArray(), state);
+            return GfxCalRGBColorSpace::parse(csObj->getArray(), state);
         } else if (obj1.isName("Lab")) {
-            cs = GfxLabColorSpace::parse(csObj->getArray(), state);
+            return GfxLabColorSpace::parse(csObj->getArray(), state);
         } else if (obj1.isName("ICCBased")) {
-            cs = GfxICCBasedColorSpace::parse(csObj->getArray(), out, state, recursion);
+            return GfxICCBasedColorSpace::parse(csObj->getArray(), out, state, recursion);
         } else if (obj1.isName("Indexed") || obj1.isName("I")) {
-            cs = GfxIndexedColorSpace::parse(res, csObj->getArray(), out, state, recursion);
+            return GfxIndexedColorSpace::parse(res, csObj->getArray(), out, state, recursion);
         } else if (obj1.isName("Separation")) {
-            cs = GfxSeparationColorSpace::parse(res, csObj->getArray(), out, state, recursion);
+            return GfxSeparationColorSpace::parse(res, csObj->getArray(), out, state, recursion);
         } else if (obj1.isName("DeviceN")) {
-            cs = GfxDeviceNColorSpace::parse(res, csObj->getArray(), out, state, recursion);
+            return GfxDeviceNColorSpace::parse(res, csObj->getArray(), out, state, recursion);
         } else if (obj1.isName("Pattern")) {
-            cs = GfxPatternColorSpace::parse(res, csObj->getArray(), out, state, recursion);
+            return GfxPatternColorSpace::parse(res, csObj->getArray(), out, state, recursion);
         } else {
             error(errSyntaxWarning, -1, "Bad color space");
         }
@@ -329,34 +327,34 @@
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultGray");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultGrayColorSpace();
+                    return state->copyDefaultGrayColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultGrayColorSpace();
+                return state->copyDefaultGrayColorSpace();
             }
         } else if (obj1.isName("DeviceRGB")) {
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultRGB");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultRGBColorSpace();
+                    return state->copyDefaultRGBColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultRGBColorSpace();
+                return state->copyDefaultRGBColorSpace();
             }
         } else if (obj1.isName("DeviceCMYK")) {
             if (res != nullptr) {
                 Object objCS = res->lookupColorSpace("DefaultCMYK");
                 if (objCS.isNull()) {
-                    cs = state->copyDefaultCMYKColorSpace();
+                    return state->copyDefaultCMYKColorSpace();
                 } else {
-                    cs = GfxColorSpace::parse(nullptr, &objCS, out, state);
+                    return GfxColorSpace::parse(nullptr, &objCS, out, state);
                 }
             } else {
-                cs = state->copyDefaultCMYKColorSpace();
+                return state->copyDefaultCMYKColorSpace();
             }
         } else {
             error(errSyntaxWarning, -1, "Bad color space dict'");
@@ -364,10 +362,10 @@
     } else {
         error(errSyntaxWarning, -1, "Bad color space - expected name or array or dict");
     }
-    return cs;
+    return {};
 }
 
-void GfxColorSpace::createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps)
+void GfxColorSpace::createMapping(std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList, int maxSepComps)
 {
     return;
 }
@@ -527,9 +525,9 @@
 
 GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() { }
 
-GfxColorSpace *GfxDeviceGrayColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxDeviceGrayColorSpace::copy() const
 {
-    return new GfxDeviceGrayColorSpace();
+    return std::make_unique<GfxDeviceGrayColorSpace>();
 }
 
 void GfxDeviceGrayColorSpace::getGray(const GfxColor *color, GfxGray *gray) const
@@ -626,11 +624,9 @@
 
 GfxCalGrayColorSpace::~GfxCalGrayColorSpace() { }
 
-GfxColorSpace *GfxCalGrayColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxCalGrayColorSpace::copy() const
 {
-    GfxCalGrayColorSpace *cs;
-
-    cs = new GfxCalGrayColorSpace();
+    auto cs = std::make_unique<GfxCalGrayColorSpace>();
     cs->whiteX = whiteX;
     cs->whiteY = whiteY;
     cs->whiteZ = whiteZ;
@@ -718,17 +714,16 @@
     Z = -0.00802913 * rho_in + 0.04166125 * gamma_in + 1.05519788 * beta_in;
 }
 
-GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr, GfxState *state)
+std::unique_ptr<GfxColorSpace> GfxCalGrayColorSpace::parse(Array *arr, GfxState *state)
 {
-    GfxCalGrayColorSpace *cs;
     Object obj1, obj2;
 
     obj1 = arr->get(1);
     if (!obj1.isDict()) {
         error(errSyntaxWarning, -1, "Bad CalGray color space");
-        return nullptr;
+        return {};
     }
-    cs = new GfxCalGrayColorSpace();
+    auto cs = std::make_unique<GfxCalGrayColorSpace>();
     obj2 = obj1.dictLookup("WhitePoint");
     if (obj2.isArray() && obj2.arrayGetLength() == 3) {
         cs->whiteX = obj2.arrayGet(0).getNumWithDefaultValue(1);
@@ -882,9 +877,9 @@
 
 GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() { }
 
-GfxColorSpace *GfxDeviceRGBColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxDeviceRGBColorSpace::copy() const
 {
-    return new GfxDeviceRGBColorSpace();
+    return std::make_unique<GfxDeviceRGBColorSpace>();
 }
 
 void GfxDeviceRGBColorSpace::getGray(const GfxColor *color, GfxGray *gray) const
@@ -1045,12 +1040,11 @@
 
 GfxCalRGBColorSpace::~GfxCalRGBColorSpace() { }
 
-GfxColorSpace *GfxCalRGBColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxCalRGBColorSpace::copy() const
 {
-    GfxCalRGBColorSpace *cs;
     int i;
 
-    cs = new GfxCalRGBColorSpace();
+    auto cs = std::make_unique<GfxCalRGBColorSpace>();
     cs->whiteX = whiteX;
     cs->whiteY = whiteY;
     cs->whiteZ = whiteZ;
@@ -1069,18 +1063,17 @@
     return cs;
 }
 
-GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr, GfxState *state)
+std::unique_ptr<GfxColorSpace> GfxCalRGBColorSpace::parse(Array *arr, GfxState *state)
 {
-    GfxCalRGBColorSpace *cs;
     Object obj1, obj2;
     int i;
 
     obj1 = arr->get(1);
     if (!obj1.isDict()) {
         error(errSyntaxWarning, -1, "Bad CalRGB color space");
-        return nullptr;
+        return {};
     }
-    cs = new GfxCalRGBColorSpace();
+    auto cs = std::make_unique<GfxCalRGBColorSpace>();
     obj2 = obj1.dictLookup("WhitePoint");
     if (obj2.isArray() && obj2.arrayGetLength() == 3) {
         cs->whiteX = obj2.arrayGet(0).getNumWithDefaultValue(1);
@@ -1252,9 +1245,9 @@
 
 GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() { }
 
-GfxColorSpace *GfxDeviceCMYKColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxDeviceCMYKColorSpace::copy() const
 {
-    return new GfxDeviceCMYKColorSpace();
+    return std::make_unique<GfxDeviceCMYKColorSpace>();
 }
 
 void GfxDeviceCMYKColorSpace::getGray(const GfxColor *color, GfxGray *gray) const
@@ -1392,11 +1385,9 @@
 
 GfxLabColorSpace::~GfxLabColorSpace() { }
 
-GfxColorSpace *GfxLabColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxLabColorSpace::copy() const
 {
-    GfxLabColorSpace *cs;
-
-    cs = new GfxLabColorSpace();
+    auto cs = std::make_unique<GfxLabColorSpace>();
     cs->whiteX = whiteX;
     cs->whiteY = whiteY;
     cs->whiteZ = whiteZ;
@@ -1413,17 +1404,16 @@
     return cs;
 }
 
-GfxColorSpace *GfxLabColorSpace::parse(Array *arr, GfxState *state)
+std::unique_ptr<GfxColorSpace> GfxLabColorSpace::parse(Array *arr, GfxState *state)
 {
-    GfxLabColorSpace *cs;
     Object obj1, obj2;
 
     obj1 = arr->get(1);
     if (!obj1.isDict()) {
         error(errSyntaxWarning, -1, "Bad Lab color space");
-        return nullptr;
+        return {};
     }
-    cs = new GfxLabColorSpace();
+    auto cs = std::make_unique<GfxLabColorSpace>();
     bool ok = true;
     obj2 = obj1.dictLookup("WhitePoint");
     if (obj2.isArray() && obj2.arrayGetLength() == 3) {
@@ -1450,8 +1440,7 @@
 #ifdef USE_CMS
         cs->transform = nullptr;
 #endif
-        delete cs;
-        return nullptr;
+        return {};
     }
 
 #ifdef USE_CMS
@@ -1648,10 +1637,9 @@
 // GfxICCBasedColorSpace
 //------------------------------------------------------------------------
 
-GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, const Ref *iccProfileStreamA)
+GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, std::unique_ptr<GfxColorSpace> &&altA, const Ref *iccProfileStreamA) : alt(std::move(altA))
 {
     nComps = nCompsA;
-    alt = altA;
     iccProfileStream = *iccProfileStreamA;
     rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
     rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
@@ -1664,7 +1652,6 @@
 
 GfxICCBasedColorSpace::~GfxICCBasedColorSpace()
 {
-    delete alt;
 #ifdef USE_CMS
     if (psCSA) {
         gfree(psCSA);
@@ -1672,12 +1659,16 @@
 #endif
 }
 
-GfxColorSpace *GfxICCBasedColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxICCBasedColorSpace::copy() const
 {
-    GfxICCBasedColorSpace *cs;
+    return copyAsOwnType();
+}
+
+std::unique_ptr<GfxICCBasedColorSpace> GfxICCBasedColorSpace::copyAsOwnType() const
+{
     int i;
 
-    cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
+    auto cs = std::make_unique<GfxICCBasedColorSpace>(nComps, alt->copy(), &iccProfileStream);
     for (i = 0; i < 4; ++i) {
         cs->rangeMin[i] = rangeMin[i];
         cs->rangeMax[i] = rangeMax[i];
@@ -1690,18 +1681,16 @@
     return cs;
 }
 
-GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState *state, int recursion)
+std::unique_ptr<GfxColorSpace> GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState *state, int recursion)
 {
-    GfxICCBasedColorSpace *cs;
     int nCompsA;
-    GfxColorSpace *altA;
     Dict *dict;
     Object obj1, obj2;
     int i;
 
     if (arr->getLength() < 2) {
         error(errSyntaxError, -1, "Bad ICCBased color space");
-        return nullptr;
+        return {};
     }
     const Object &obj1Ref = arr->getNF(1);
     const Ref iccProfileStreamA = obj1Ref.isRef() ? obj1Ref.getRef() : Ref::INVALID();
@@ -1709,7 +1698,7 @@
     // check cache
     if (out && iccProfileStreamA != Ref::INVALID()) {
         if (auto *item = out->getIccColorSpaceCache()->lookup(iccProfileStreamA)) {
-            cs = static_cast<GfxICCBasedColorSpace *>(item->copy());
+            std::unique_ptr<GfxICCBasedColorSpace> cs = item->copyAsOwnType();
             int transformIntent = cs->getIntent();
             int cmsIntent = INTENT_RELATIVE_COLORIMETRIC;
             if (state != nullptr) {
@@ -1718,7 +1707,6 @@
             if (transformIntent == cmsIntent) {
                 return cs;
             }
-            delete cs;
         }
     }
 #endif
@@ -1739,16 +1727,17 @@
         nCompsA = 4;
     }
     obj2 = dict->lookup("Alternate");
+    std::unique_ptr<GfxColorSpace> altA;
     if (obj2.isNull() || !(altA = GfxColorSpace::parse(nullptr, &obj2, out, state, recursion + 1))) {
         switch (nCompsA) {
         case 1:
-            altA = new GfxDeviceGrayColorSpace();
+            altA = std::make_unique<GfxDeviceGrayColorSpace>();
             break;
         case 3:
-            altA = new GfxDeviceRGBColorSpace();
+            altA = std::make_unique<GfxDeviceRGBColorSpace>();
             break;
         case 4:
-            altA = new GfxDeviceCMYKColorSpace();
+            altA = std::make_unique<GfxDeviceCMYKColorSpace>();
             break;
         default:
             error(errSyntaxWarning, -1, "Bad ICCBased color space - invalid N");
@@ -1757,10 +1746,9 @@
     }
     if (altA->getNComps() != nCompsA) {
         error(errSyntaxWarning, -1, "Bad ICCBased color space - N doesn't match alt color space");
-        delete altA;
-        return nullptr;
+        return {};
     }
-    cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
+    auto cs = std::make_unique<GfxICCBasedColorSpace>(nCompsA, std::move(altA), &iccProfileStreamA);
     obj2 = dict->lookup("Range");
     if (obj2.isArray() && obj2.arrayGetLength() == 2 * nCompsA) {
         for (i = 0; i < nCompsA; ++i) {
@@ -1773,8 +1761,7 @@
     obj1 = arr->get(1);
     if (!obj1.isStream()) {
         error(errSyntaxWarning, -1, "Bad ICCBased color space (stream)");
-        delete cs;
-        return nullptr;
+        return {};
     }
     Stream *iccStream = obj1.getStream();
 
@@ -1788,7 +1775,7 @@
     }
     // put this colorSpace into cache
     if (out && iccProfileStreamA != Ref::INVALID()) {
-        out->getIccColorSpaceCache()->put(iccProfileStreamA, static_cast<GfxICCBasedColorSpace *>(cs->copy()));
+        out->getIccColorSpaceCache()->put(iccProfileStreamA, cs->copyAsOwnType());
     }
 #endif
     return cs;
@@ -2339,9 +2326,8 @@
 // GfxIndexedColorSpace
 //------------------------------------------------------------------------
 
-GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA)
+GfxIndexedColorSpace::GfxIndexedColorSpace(std::unique_ptr<GfxColorSpace> &&baseA, int indexHighA) : base(std::move(baseA))
 {
-    base = baseA;
     indexHigh = indexHighA;
     lookup = (unsigned char *)gmallocn((indexHigh + 1) * base->getNComps(), sizeof(unsigned char));
     overprintMask = base->getOverprintMask();
@@ -2349,22 +2335,20 @@
 
 GfxIndexedColorSpace::~GfxIndexedColorSpace()
 {
-    delete base;
     gfree(lookup);
 }
 
-GfxColorSpace *GfxIndexedColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxIndexedColorSpace::copy() const
 {
-    GfxIndexedColorSpace *cs;
 
-    cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
+    auto cs = std::make_unique<GfxIndexedColorSpace>(base->copy(), indexHigh);
     memcpy(cs->lookup, lookup, (indexHigh + 1) * base->getNComps() * sizeof(unsigned char));
     return cs;
 }
 
-GfxColorSpace *GfxIndexedColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
+std::unique_ptr<GfxColorSpace> GfxIndexedColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
 {
-    GfxColorSpace *baseA;
+    std::unique_ptr<GfxColorSpace> baseA;
     int indexHighA;
     Object obj1;
     const char *s;
@@ -2377,13 +2361,12 @@
     obj1 = arr->get(1);
     if (!(baseA = GfxColorSpace::parse(res, &obj1, out, state, recursion + 1))) {
         error(errSyntaxWarning, -1, "Bad Indexed color space (base color space)");
-        return nullptr;
+        return {};
     }
     obj1 = arr->get(2);
     if (!obj1.isInt()) {
         error(errSyntaxWarning, -1, "Bad Indexed color space (hival)");
-        delete baseA;
-        return nullptr;
+        return {};
     }
     indexHighA = obj1.getInt();
     if (indexHighA < 0 || indexHighA > 255) {
@@ -2399,9 +2382,9 @@
         }
         error(errSyntaxWarning, -1, "Bad Indexed color space (invalid indexHigh value, was {0:d} using {1:d} to try to recover)", previousValue, indexHighA);
     }
-    GfxIndexedColorSpace *cs = new GfxIndexedColorSpace(baseA, indexHighA);
+    auto cs = std::make_unique<GfxIndexedColorSpace>(std::move(baseA), indexHighA);
     obj1 = arr->get(3);
-    const int n = baseA->getNComps();
+    const int n = cs->getBase()->getNComps();
     if (obj1.isStream()) {
         obj1.streamReset();
         for (i = 0; i <= indexHighA; ++i) {
@@ -2430,8 +2413,7 @@
     return cs;
 
 err3:
-    delete cs;
-    return nullptr;
+    return {};
 }
 
 GfxColor *GfxIndexedColorSpace::mapColorToBase(const GfxColor *color, GfxColor *baseColor) const
@@ -2589,10 +2571,9 @@
 // GfxSeparationColorSpace
 //------------------------------------------------------------------------
 
-GfxSeparationColorSpace::GfxSeparationColorSpace(GooString *nameA, GfxColorSpace *altA, Function *funcA)
+GfxSeparationColorSpace::GfxSeparationColorSpace(GooString *nameA, std::unique_ptr<GfxColorSpace> &&altA, Function *funcA) : alt(std::move(altA))
 {
     name = nameA;
-    alt = altA;
     func = funcA;
     nonMarking = !name->cmp("None");
     if (!name->cmp("Cyan")) {
@@ -2608,10 +2589,9 @@
     }
 }
 
-GfxSeparationColorSpace::GfxSeparationColorSpace(GooString *nameA, GfxColorSpace *altA, Function *funcA, bool nonMarkingA, unsigned int overprintMaskA, int *mappingA)
+GfxSeparationColorSpace::GfxSeparationColorSpace(GooString *nameA, std::unique_ptr<GfxColorSpace> &&altA, Function *funcA, bool nonMarkingA, unsigned int overprintMaskA, int *mappingA) : alt(std::move(altA))
 {
     name = nameA;
-    alt = altA;
     func = funcA;
     nonMarking = nonMarkingA;
     overprintMask = overprintMaskA;
@@ -2621,28 +2601,33 @@
 GfxSeparationColorSpace::~GfxSeparationColorSpace()
 {
     delete name;
-    delete alt;
     delete func;
     if (mapping != nullptr) {
         gfree(mapping);
     }
 }
 
-GfxColorSpace *GfxSeparationColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxSeparationColorSpace::copy() const
+{
+    return copyAsOwnType();
+}
+
+std::unique_ptr<GfxSeparationColorSpace> GfxSeparationColorSpace::copyAsOwnType() const
 {
     int *mappingA = nullptr;
     if (mapping != nullptr) {
         mappingA = (int *)gmalloc(sizeof(int));
         *mappingA = *mapping;
     }
-    return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(), nonMarking, overprintMask, mappingA);
+    auto cs = new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(), nonMarking, overprintMask, mappingA);
+    return std::unique_ptr<GfxSeparationColorSpace>(cs);
 }
 
 //~ handle the 'All' and 'None' colorants
-GfxColorSpace *GfxSeparationColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
+std::unique_ptr<GfxColorSpace> GfxSeparationColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
 {
     GooString *nameA;
-    GfxColorSpace *altA;
+    std::unique_ptr<GfxColorSpace> altA;
     Function *funcA;
     Object obj1;
 
@@ -2663,24 +2648,22 @@
     }
     obj1 = arr->get(3);
     if (!(funcA = Function::parse(&obj1))) {
-        goto err4;
+        goto err3;
     }
     if (funcA->getInputSize() != 1) {
         error(errSyntaxWarning, -1, "Bad SeparationColorSpace function");
         goto err5;
     }
     if (altA->getNComps() <= funcA->getOutputSize()) {
-        return new GfxSeparationColorSpace(nameA, altA, funcA);
+        return std::make_unique<GfxSeparationColorSpace>(nameA, std::move(altA), funcA);
     }
 
 err5:
     delete funcA;
-err4:
-    delete altA;
 err3:
     delete nameA;
 err1:
-    return nullptr;
+    return {};
 }
 
 void GfxSeparationColorSpace::getGray(const GfxColor *color, GfxGray *gray) const
@@ -2782,7 +2765,7 @@
     color->c[0] = gfxColorComp1;
 }
 
-void GfxSeparationColorSpace::createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps)
+void GfxSeparationColorSpace::createMapping(std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList, int maxSepComps)
 {
     if (nonMarking) {
         return;
@@ -2804,7 +2787,7 @@
     default:
         unsigned int newOverprintMask = 0x10;
         for (std::size_t i = 0; i < separationList->size(); i++) {
-            GfxSeparationColorSpace *sepCS = (*separationList)[i];
+            const std::unique_ptr<GfxSeparationColorSpace> &sepCS = (*separationList)[i];
             if (!sepCS->getName()->cmp(name)) {
                 if (sepCS->getFunc()->hasDifferentResultSet(func)) {
                     error(errSyntaxWarning, -1, "Different functions found for '{0:t}', convert immediately", name);
@@ -2825,7 +2808,7 @@
             return;
         }
         *mapping = separationList->size() + 4;
-        separationList->push_back((GfxSeparationColorSpace *)copy());
+        separationList->push_back(copyAsOwnType());
         overprintMask = newOverprintMask;
         break;
     }
@@ -2835,9 +2818,9 @@
 // GfxDeviceNColorSpace
 //------------------------------------------------------------------------
 
-GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, std::vector<std::string> &&namesA, GfxColorSpace *altA, Function *funcA, std::vector<GfxSeparationColorSpace *> *sepsCSA) : nComps(nCompsA), names(std::move(namesA))
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, std::vector<std::string> &&namesA, std::unique_ptr<GfxColorSpace> &&altA, Function *funcA, std::vector<std::unique_ptr<GfxSeparationColorSpace>> *sepsCSA)
+    : nComps(nCompsA), names(std::move(namesA)), alt(std::move(altA))
 {
-    alt = altA;
     func = funcA;
     sepsCS = sepsCSA;
     nonMarking = true;
@@ -2863,11 +2846,10 @@
     }
 }
 
-GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, const std::vector<std::string> &namesA, GfxColorSpace *altA, Function *funcA, std::vector<GfxSeparationColorSpace *> *sepsCSA, int *mappingA, bool nonMarkingA,
-                                           unsigned int overprintMaskA)
-    : nComps(nCompsA), names(namesA)
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, const std::vector<std::string> &namesA, std::unique_ptr<GfxColorSpace> &&altA, Function *funcA, std::vector<std::unique_ptr<GfxSeparationColorSpace>> *sepsCSA, int *mappingA,
+                                           bool nonMarkingA, unsigned int overprintMaskA)
+    : nComps(nCompsA), names(namesA), alt(std::move(altA))
 {
-    alt = altA;
     func = funcA;
     sepsCS = sepsCSA;
     mapping = mappingA;
@@ -2877,26 +2859,22 @@
 
 GfxDeviceNColorSpace::~GfxDeviceNColorSpace()
 {
-    delete alt;
     delete func;
-    for (auto entry : *sepsCS) {
-        delete entry;
-    }
     delete sepsCS;
     if (mapping != nullptr) {
         gfree(mapping);
     }
 }
 
-GfxColorSpace *GfxDeviceNColorSpace::copy() const
+std::unique_ptr<GfxColorSpace> GfxDeviceNColorSpace::copy() const
 {
     int *mappingA = nullptr;
 
-    auto sepsCSA = new std::vector<GfxSeparationColorSpace *>();
+    auto sepsCSA = new std::vector<std::unique_ptr<GfxSeparationColorSpace>>();
     sepsCSA->reserve(sepsCS->size());
-    for (const GfxSeparationColorSpace *scs : *sepsCS) {
+    for (const std::unique_ptr<GfxSeparationColorSpace> &scs : *sepsCS) {
         if (likely(scs != nullptr)) {
-            sepsCSA->push_back((GfxSeparationColorSpace *)scs->copy());
+            sepsCSA->push_back(scs->copyAsOwnType());
         }
     }
     if (mapping != nullptr) {
@@ -2905,18 +2883,19 @@
             mappingA[i] = mapping[i];
         }
     }
-    return new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(), sepsCSA, mappingA, nonMarking, overprintMask);
+    auto cs = new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(), sepsCSA, mappingA, nonMarking, overprintMask);
+    return std::unique_ptr<GfxDeviceNColorSpace>(cs);
 }
 
 //~ handle the 'None' colorant
-GfxColorSpace *GfxDeviceNColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
+std::unique_ptr<GfxColorSpace> GfxDeviceNColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
 {
     int nCompsA;
     std::vector<std::string> namesA;
-    GfxColorSpace *altA;
+    std::unique_ptr<GfxColorSpace> altA;
     Function *funcA;
     Object obj1;
-    auto separationList = new std::vector<GfxSeparationColorSpace *>();
+    auto separationList = new std::vector<std::unique_ptr<GfxSeparationColorSpace>>();
 
     if (arr->getLength() != 4 && arr->getLength() != 5) {
         error(errSyntaxWarning, -1, "Bad DeviceN color space");
@@ -2948,7 +2927,7 @@
     }
     obj1 = arr->get(3);
     if (!(funcA = Function::parse(&obj1))) {
-        goto err4;
+        goto err1;
     }
     if (arr->getLength() == 5) {
         obj1 = arr->get(4);
@@ -2963,9 +2942,9 @@
             for (int i = 0; i < colorants->getLength(); i++) {
                 Object obj3 = colorants->getVal(i);
                 if (obj3.isArray()) {
-                    GfxSeparationColorSpace *cs = (GfxSeparationColorSpace *)GfxSeparationColorSpace::parse(res, obj3.getArray(), out, state, recursion);
+                    auto cs = GfxSeparationColorSpace::parse(res, obj3.getArray(), out, state, recursion);
                     if (cs) {
-                        separationList->push_back(cs);
+                        separationList->push_back(std::unique_ptr<GfxSeparationColorSpace>(static_cast<GfxSeparationColorSpace *>(cs.release())));
                     }
                 } else {
                     error(errSyntaxWarning, -1, "Bad DeviceN color space (colorant value entry is not an Array)");
@@ -2976,13 +2955,11 @@
     }
 
     if (likely(nCompsA >= funcA->getInputSize() && altA->getNComps() <= funcA->getOutputSize())) {
-        return new GfxDeviceNColorSpace(nCompsA, std::move(namesA), altA, funcA, separationList);
+        return std::make_unique<GfxDeviceNColorSpace>(nCompsA, std::move(namesA), std::move(altA), funcA, separationList);
     }
 
 err5:
     delete funcA;
-err4:
-    delete altA;
 err1:
     delete separationList;
     return nullptr;
@@ -3065,7 +3042,7 @@
     }
 }
 
-void GfxDeviceNColorSpace::createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps)
+void GfxDeviceNColorSpace::createMapping(std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList, int maxSepComps)
 {
     if (nonMarking) { // None
         return;
@@ -3094,7 +3071,7 @@
             if (nComps == 1) {
                 sepFunc = func;
             } else {
-                for (const GfxSeparationColorSpace *sepCS : *sepsCS) {
+                for (const std::unique_ptr<GfxSeparationColorSpace> &sepCS : *sepsCS) {
                     if (!sepCS->getName()->cmp(names[i])) {
                         sepFunc = sepCS->getFunc();
                         break;
@@ -3102,7 +3079,7 @@
                 }
             }
             for (std::size_t j = 0; j < separationList->size(); j++) {
-                GfxSeparationColorSpace *sepCS = (*separationList)[j];
+                const std::unique_ptr<GfxSeparationColorSpace> &sepCS = (*separationList)[j];
                 if (!sepCS->getName()->cmp(names[i])) {
                     if (sepFunc != nullptr && sepCS->getFunc()->hasDifferentResultSet(sepFunc)) {
                         error(errSyntaxWarning, -1, "Different functions found for '{0:s}', convert immediately", names[i].c_str());
@@ -3129,12 +3106,12 @@
                 mapping[i] = separationList->size() + 4;
                 newOverprintMask |= startOverprintMask;
                 if (nComps == 1) {
-                    separationList->push_back(new GfxSeparationColorSpace(new GooString(names[i]), alt->copy(), func->copy()));
+                    separationList->push_back(std::make_unique<GfxSeparationColorSpace>(new GooString(names[i]), alt->copy(), func->copy()));
                 } else {
-                    for (const GfxSeparationColorSpace *sepCS : *sepsCS) {
+                    for (const std::unique_ptr<GfxSeparationColorSpace> &sepCS : *sepsCS) {
                         if (!sepCS->getName()->cmp(names[i])) {
                             found = true;
-                            separationList->push_back((GfxSeparationColorSpace *)sepCS->copy());
+                            separationList->push_back(sepCS->copyAsOwnType());
                             break;
                         }
                     }
@@ -3156,43 +3133,32 @@
 // GfxPatternColorSpace
 //------------------------------------------------------------------------
 
-GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA)
+GfxPatternColorSpace::GfxPatternColorSpace(std::unique_ptr<GfxColorSpace> &&underA) : under(std::move(underA)) { }
+
+GfxPatternColorSpace::~GfxPatternColorSpace() { }
+
+std::unique_ptr<GfxColorSpace> GfxPatternColorSpace::copy() const
 {
-    under = underA;
+    return std::make_unique<GfxPatternColorSpace>(under ? under->copy() : nullptr);
 }
 
-GfxPatternColorSpace::~GfxPatternColorSpace()
+std::unique_ptr<GfxColorSpace> GfxPatternColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
 {
-    if (under) {
-        delete under;
-    }
-}
-
-GfxColorSpace *GfxPatternColorSpace::copy() const
-{
-    return new GfxPatternColorSpace(under ? under->copy() : nullptr);
-}
-
-GfxColorSpace *GfxPatternColorSpace::parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion)
-{
-    GfxPatternColorSpace *cs;
-    GfxColorSpace *underA;
     Object obj1;
 
     if (arr->getLength() != 1 && arr->getLength() != 2) {
         error(errSyntaxWarning, -1, "Bad Pattern color space");
-        return nullptr;
+        return {};
     }
-    underA = nullptr;
+    std::unique_ptr<GfxColorSpace> underA;
     if (arr->getLength() == 2) {
         obj1 = arr->get(1);
         if (!(underA = GfxColorSpace::parse(res, &obj1, out, state, recursion + 1))) {
             error(errSyntaxWarning, -1, "Bad Pattern color space (underlying color space)");
-            return nullptr;
+            return {};
         }
     }
-    cs = new GfxPatternColorSpace(underA);
-    return cs;
+    return std::make_unique<GfxPatternColorSpace>(std::move(underA));
 }
 
 void GfxPatternColorSpace::getGray(const GfxColor *color, GfxGray *gray) const
@@ -3429,7 +3395,6 @@
 GfxShading::GfxShading(int typeA)
 {
     type = static_cast<ShadingType>(typeA);
-    colorSpace = nullptr;
 }
 
 GfxShading::GfxShading(const GfxShading *shading)
@@ -3449,12 +3414,7 @@
     hasBBox = shading->hasBBox;
 }
 
-GfxShading::~GfxShading()
-{
-    if (colorSpace) {
-        delete colorSpace;
-    }
-}
+GfxShading::~GfxShading() = default;
 
 GfxShading *GfxShading::parse(GfxResources *res, Object *obj, OutputDev *out, GfxState *state)
 {
@@ -5570,10 +5530,8 @@
 // GfxImageColorMap
 //------------------------------------------------------------------------
 
-GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA)
+GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, std::unique_ptr<GfxColorSpace> &&colorSpaceA) : colorSpace(std::move(colorSpaceA))
 {
-    GfxIndexedColorSpace *indexedCS;
-    GfxSeparationColorSpace *sepCS;
     int maxPixel, indexHigh;
     unsigned char *indexedLookup;
     const Function *sepFunc;
@@ -5586,8 +5544,6 @@
     ok = true;
     useMatte = false;
 
-    colorSpace = colorSpaceA;
-
     // initialize
     for (k = 0; k < gfxColorMaxComps; ++k) {
         lookup[k] = nullptr;
@@ -5657,11 +5613,11 @@
     nComps2 = 0;
     useByteLookup = false;
     switch (colorSpace->getMode()) {
-    case csIndexed:
+    case csIndexed: {
         // Note that indexHigh may not be the same as maxPixel --
         // Distiller will remove unused palette entries, resulting in
         // indexHigh < maxPixel.
-        indexedCS = (GfxIndexedColorSpace *)colorSpace;
+        GfxIndexedColorSpace *indexedCS = (GfxIndexedColorSpace *)colorSpace.get();
         colorSpace2 = indexedCS->getBase();
         indexHigh = indexedCS->getIndexHigh();
         nComps2 = colorSpace2->getNComps();
@@ -5689,8 +5645,9 @@
             }
         }
         break;
-    case csSeparation:
-        sepCS = (GfxSeparationColorSpace *)colorSpace;
+    }
+    case csSeparation: {
+        GfxSeparationColorSpace *sepCS = (GfxSeparationColorSpace *)colorSpace.get();
         colorSpace2 = sepCS->getAlt();
         nComps2 = colorSpace2->getNComps();
         sepFunc = sepCS->getFunc();
@@ -5710,6 +5667,7 @@
             }
         }
         break;
+    }
     default:
         if ((!decode->isNull() || maxPixel != 255) && (colorSpace->useGetGrayLine() || (colorSpace->useGetRGBLine() && !decode->isNull()) || colorSpace->useGetCMYKLine() || colorSpace->useGetDeviceNLine())) {
             byte_lookup = (unsigned char *)gmallocn((maxPixel + 1), nComps);
@@ -5763,13 +5721,13 @@
         memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp));
     }
     if (colorSpace->getMode() == csIndexed) {
-        colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
+        colorSpace2 = ((GfxIndexedColorSpace *)colorSpace.get())->getBase();
         for (k = 0; k < nComps2; ++k) {
             lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
             memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp));
         }
     } else if (colorSpace->getMode() == csSeparation) {
-        colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
+        colorSpace2 = ((GfxSeparationColorSpace *)colorSpace.get())->getAlt();
         for (k = 0; k < nComps2; ++k) {
             lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp));
             memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp));
@@ -5797,7 +5755,6 @@
 {
     int i;
 
-    delete colorSpace;
     for (i = 0; i < gfxColorMaxComps; ++i) {
         gfree(lookup[i]);
         gfree(lookup2[i]);
@@ -6490,8 +6447,8 @@
         pageHeight = ky * (py2 - py1);
     }
 
-    fillColorSpace = new GfxDeviceGrayColorSpace();
-    strokeColorSpace = new GfxDeviceGrayColorSpace();
+    fillColorSpace = std::make_unique<GfxDeviceGrayColorSpace>();
+    strokeColorSpace = std::make_unique<GfxDeviceGrayColorSpace>();
     fillColor.c[0] = 0;
     strokeColor.c[0] = 0;
     fillPattern = nullptr;
@@ -6569,18 +6526,6 @@
 {
     int i;
 
-    if (fillColorSpace) {
-        delete fillColorSpace;
-    }
-    if (strokeColorSpace) {
-        delete strokeColorSpace;
-    }
-    if (fillPattern) {
-        delete fillPattern;
-    }
-    if (strokePattern) {
-        delete strokePattern;
-    }
     for (i = 0; i < 4; ++i) {
         if (transfer[i]) {
             delete transfer[i];
@@ -6590,10 +6535,6 @@
         // this gets set to NULL by restore()
         delete path;
     }
-
-    delete defaultGrayColorSpace;
-    delete defaultRGBColorSpace;
-    delete defaultCMYKColorSpace;
 }
 
 // Used for copy();
@@ -6612,12 +6553,10 @@
     pageHeight = state->pageHeight;
     rotate = state->rotate;
 
-    fillColorSpace = state->fillColorSpace;
-    if (fillColorSpace) {
+    if (state->fillColorSpace) {
         fillColorSpace = state->fillColorSpace->copy();
     }
-    strokeColorSpace = state->strokeColorSpace;
-    if (strokeColorSpace) {
+    if (state->strokeColorSpace) {
         strokeColorSpace = state->strokeColorSpace->copy();
     }
     fillColor = state->fillColor;
@@ -6916,20 +6855,14 @@
     clipYMax += ty;
 }
 
-void GfxState::setFillColorSpace(GfxColorSpace *colorSpace)
+void GfxState::setFillColorSpace(std::unique_ptr<GfxColorSpace> &&colorSpace)
 {
-    if (fillColorSpace) {
-        delete fillColorSpace;
-    }
-    fillColorSpace = colorSpace;
+    fillColorSpace = std::move(colorSpace);
 }
 
-void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace)
+void GfxState::setStrokeColorSpace(std::unique_ptr<GfxColorSpace> &&colorSpace)
 {
-    if (strokeColorSpace) {
-        delete strokeColorSpace;
-    }
-    strokeColorSpace = colorSpace;
+    strokeColorSpace = std::move(colorSpace);
 }
 
 void GfxState::setFillPattern(GfxPattern *pattern)
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 8ff98ec..4bf2b8f 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -17,7 +17,7 @@
 // Copyright (C) 2006, 2007 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2009 Koji Otani <sho@bbr.jp>
-// Copyright (C) 2009-2011, 2013, 2016-2022 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2009-2011, 2013, 2016-2022, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
 // Copyright (C) 2011-2014, 2016, 2020 Thomas Freitag <Thomas.Freitag@alfa.de>
@@ -255,11 +255,11 @@
     GfxColorSpace(const GfxColorSpace &) = delete;
     GfxColorSpace &operator=(const GfxColorSpace &other) = delete;
 
-    virtual GfxColorSpace *copy() const = 0;
+    virtual std::unique_ptr<GfxColorSpace> copy() const = 0;
     virtual GfxColorSpaceMode getMode() const = 0;
 
     // Construct a color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(GfxResources *res, Object *csObj, OutputDev *out, GfxState *state, int recursion = 0);
+    static std::unique_ptr<GfxColorSpace> parse(GfxResources *res, Object *csObj, OutputDev *out, GfxState *state, int recursion = 0);
 
     // Convert to gray, RGB, or CMYK.
     virtual void getGray(const GfxColor *color, GfxGray *gray) const = 0;
@@ -274,7 +274,7 @@
     virtual void getDeviceNLine(unsigned char * /*in*/, unsigned char * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getDeviceNLine this should not happen"); }
 
     // create mapping for spot colorants
-    virtual void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps);
+    virtual void createMapping(std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList, int maxSepComps);
     int *getMapping() const { return mapping; }
 
     // Does this ColorSpace support getRGBLine?
@@ -323,7 +323,7 @@
 public:
     GfxDeviceGrayColorSpace();
     ~GfxDeviceGrayColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csDeviceGray; }
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
@@ -357,11 +357,11 @@
 public:
     GfxCalGrayColorSpace();
     ~GfxCalGrayColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csCalGray; }
 
     // Construct a CalGray color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(Array *arr, GfxState *state);
+    static std::unique_ptr<GfxColorSpace> parse(Array *arr, GfxState *state);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
@@ -399,7 +399,7 @@
 public:
     GfxDeviceRGBColorSpace();
     ~GfxDeviceRGBColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csDeviceRGB; }
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
@@ -433,11 +433,11 @@
 public:
     GfxCalRGBColorSpace();
     ~GfxCalRGBColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csCalRGB; }
 
     // Construct a CalRGB color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(Array *arr, GfxState *state);
+    static std::unique_ptr<GfxColorSpace> parse(Array *arr, GfxState *state);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
@@ -479,7 +479,7 @@
 public:
     GfxDeviceCMYKColorSpace();
     ~GfxDeviceCMYKColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csDeviceCMYK; }
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
@@ -510,11 +510,11 @@
 public:
     GfxLabColorSpace();
     ~GfxLabColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csLab; }
 
     // Construct a Lab color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(Array *arr, GfxState *state);
+    static std::unique_ptr<GfxColorSpace> parse(Array *arr, GfxState *state);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
@@ -555,13 +555,15 @@
 class POPPLER_PRIVATE_EXPORT GfxICCBasedColorSpace : public GfxColorSpace
 {
 public:
-    GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, const Ref *iccProfileStreamA);
+    GfxICCBasedColorSpace(int nCompsA, std::unique_ptr<GfxColorSpace> &&altA, const Ref *iccProfileStreamA);
     ~GfxICCBasedColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csICCBased; }
 
+    std::unique_ptr<GfxICCBasedColorSpace> copyAsOwnType() const;
+
     // Construct an ICCBased color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState *state, int recursion);
+    static std::unique_ptr<GfxColorSpace> parse(Array *arr, OutputDev *out, GfxState *state, int recursion);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
@@ -583,7 +585,7 @@
     void getDefaultRanges(double *decodeLow, double *decodeRange, int maxImgPixel) const override;
 
     // ICCBased-specific access.
-    GfxColorSpace *getAlt() { return alt; }
+    GfxColorSpace *getAlt() { return alt.get(); }
     Ref getRef() { return iccProfileStream; }
 #ifdef USE_CMS
     char *getPostScriptCSA();
@@ -594,7 +596,7 @@
 
 private:
     int nComps; // number of color components (1, 3, or 4)
-    GfxColorSpace *alt; // alternate color space
+    std::unique_ptr<GfxColorSpace> alt; // alternate color space
     double rangeMin[4]; // min values for each component
     double rangeMax[4]; // max values for each component
     Ref iccProfileStream; // the ICC profile
@@ -614,13 +616,13 @@
 class GfxIndexedColorSpace : public GfxColorSpace
 {
 public:
-    GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA);
+    GfxIndexedColorSpace(std::unique_ptr<GfxColorSpace> &&baseA, int indexHighA);
     ~GfxIndexedColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csIndexed; }
 
     // Construct an Indexed color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
+    static std::unique_ptr<GfxColorSpace> parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
@@ -642,15 +644,15 @@
     void getDefaultRanges(double *decodeLow, double *decodeRange, int maxImgPixel) const override;
 
     // Indexed-specific access.
-    GfxColorSpace *getBase() { return base; }
+    GfxColorSpace *getBase() { return base.get(); }
     int getIndexHigh() const { return indexHigh; }
     unsigned char *getLookup() { return lookup; }
     GfxColor *mapColorToBase(const GfxColor *color, GfxColor *baseColor) const;
     unsigned int getOverprintMask() const { return base->getOverprintMask(); }
-    void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps) override { base->createMapping(separationList, maxSepComps); }
+    void createMapping(std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList, int maxSepComps) override { base->createMapping(separationList, maxSepComps); }
 
 private:
-    GfxColorSpace *base; // base color space
+    std::unique_ptr<GfxColorSpace> base; // base color space
     int indexHigh; // max pixel value
     unsigned char *lookup; // lookup table
 };
@@ -662,20 +664,22 @@
 class GfxSeparationColorSpace : public GfxColorSpace
 {
 public:
-    GfxSeparationColorSpace(GooString *nameA, GfxColorSpace *altA, Function *funcA);
+    GfxSeparationColorSpace(GooString *nameA, std::unique_ptr<GfxColorSpace> &&altA, Function *funcA);
     ~GfxSeparationColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csSeparation; }
 
+    std::unique_ptr<GfxSeparationColorSpace> copyAsOwnType() const;
+
     // Construct a Separation color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
+    static std::unique_ptr<GfxColorSpace> parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
     void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override;
     void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override;
 
-    void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps) override;
+    void createMapping(std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList, int maxSepComps) override;
 
     int getNComps() const override { return 1; }
     void getDefaultColor(GfxColor *color) const override;
@@ -684,14 +688,14 @@
 
     // Separation-specific access.
     const GooString *getName() const { return name; }
-    GfxColorSpace *getAlt() { return alt; }
+    GfxColorSpace *getAlt() { return alt.get(); }
     const Function *getFunc() const { return func; }
 
 private:
-    GfxSeparationColorSpace(GooString *nameA, GfxColorSpace *altA, Function *funcA, bool nonMarkingA, unsigned int overprintMaskA, int *mappingA);
+    GfxSeparationColorSpace(GooString *nameA, std::unique_ptr<GfxColorSpace> &&altA, Function *funcA, bool nonMarkingA, unsigned int overprintMaskA, int *mappingA);
 
     GooString *name; // colorant name
-    GfxColorSpace *alt; // alternate color space
+    std::unique_ptr<GfxColorSpace> alt; // alternate color space
     Function *func; // tint transform (into alternate color space)
     bool nonMarking;
 };
@@ -703,20 +707,20 @@
 class GfxDeviceNColorSpace : public GfxColorSpace
 {
 public:
-    GfxDeviceNColorSpace(int nCompsA, std::vector<std::string> &&namesA, GfxColorSpace *alt, Function *func, std::vector<GfxSeparationColorSpace *> *sepsCS);
+    GfxDeviceNColorSpace(int nCompsA, std::vector<std::string> &&namesA, std::unique_ptr<GfxColorSpace> &&alt, Function *func, std::vector<std::unique_ptr<GfxSeparationColorSpace>> *sepsCS);
     ~GfxDeviceNColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csDeviceN; }
 
     // Construct a DeviceN color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
+    static std::unique_ptr<GfxColorSpace> parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
     void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override;
     void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override;
 
-    void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps) override;
+    void createMapping(std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList, int maxSepComps) override;
 
     int getNComps() const override { return nComps; }
     void getDefaultColor(GfxColor *color) const override;
@@ -725,18 +729,19 @@
 
     // DeviceN-specific access.
     const std::string &getColorantName(int i) const { return names[i]; }
-    GfxColorSpace *getAlt() { return alt; }
+    GfxColorSpace *getAlt() { return alt.get(); }
     const Function *getTintTransformFunc() const { return func; }
 
 private:
-    GfxDeviceNColorSpace(int nCompsA, const std::vector<std::string> &namesA, GfxColorSpace *alt, Function *func, std::vector<GfxSeparationColorSpace *> *sepsCSA, int *mappingA, bool nonMarkingA, unsigned int overprintMaskA);
+    GfxDeviceNColorSpace(int nCompsA, const std::vector<std::string> &namesA, std::unique_ptr<GfxColorSpace> &&alt, Function *func, std::vector<std::unique_ptr<GfxSeparationColorSpace>> *sepsCSA, int *mappingA, bool nonMarkingA,
+                         unsigned int overprintMaskA);
 
     const int nComps; // number of components
     const std::vector<std::string> names; // colorant names
-    GfxColorSpace *alt; // alternate color space
+    std::unique_ptr<GfxColorSpace> alt; // alternate color space
     Function *func; // tint transform (into alternate color space)
     bool nonMarking;
-    std::vector<GfxSeparationColorSpace *> *sepsCS; // list of separation cs for spot colorants;
+    std::vector<std::unique_ptr<GfxSeparationColorSpace>> *sepsCS; // list of separation cs for spot colorants;
 };
 
 //------------------------------------------------------------------------
@@ -746,13 +751,13 @@
 class GfxPatternColorSpace : public GfxColorSpace
 {
 public:
-    explicit GfxPatternColorSpace(GfxColorSpace *underA);
+    explicit GfxPatternColorSpace(std::unique_ptr<GfxColorSpace> &&underA);
     ~GfxPatternColorSpace() override;
-    GfxColorSpace *copy() const override;
+    std::unique_ptr<GfxColorSpace> copy() const override;
     GfxColorSpaceMode getMode() const override { return csPattern; }
 
     // Construct a Pattern color space.  Returns nullptr if unsuccessful.
-    static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
+    static std::unique_ptr<GfxColorSpace> parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion);
 
     void getGray(const GfxColor *color, GfxGray *gray) const override;
     void getRGB(const GfxColor *color, GfxRGB *rgb) const override;
@@ -763,11 +768,10 @@
     void getDefaultColor(GfxColor *color) const override;
 
     // Pattern-specific access.
-    GfxColorSpace *getUnder() { return under; }
+    GfxColorSpace *getUnder() { return under.get(); }
 
 private:
-    GfxColorSpace *under; // underlying color space (for uncolored
-                          //   patterns)
+    std::unique_ptr<GfxColorSpace> under; // underlying color space (for uncolored patterns)
 };
 
 //------------------------------------------------------------------------
@@ -881,7 +885,7 @@
     virtual GfxShading *copy() const = 0;
 
     ShadingType getType() const { return type; }
-    GfxColorSpace *getColorSpace() { return colorSpace; }
+    GfxColorSpace *getColorSpace() { return colorSpace.get(); }
     const GfxColor *getBackground() const { return &background; }
     bool getHasBackground() const { return hasBackground; }
     void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) const
@@ -899,7 +903,7 @@
     ShadingType type;
     bool hasBackground;
     bool hasBBox;
-    GfxColorSpace *colorSpace;
+    std::unique_ptr<GfxColorSpace> colorSpace;
     GfxColor background;
     double bbox_xMin, bbox_yMin, bbox_xMax, bbox_yMax;
 };
@@ -1200,7 +1204,7 @@
 {
 public:
     // Constructor.
-    GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA);
+    GfxImageColorMap(int bitsA, Object *decode, std::unique_ptr<GfxColorSpace> &&colorSpaceA);
 
     // Destructor.
     ~GfxImageColorMap();
@@ -1215,7 +1219,7 @@
     bool isOk() const { return ok; }
 
     // Get the color space.
-    GfxColorSpace *getColorSpace() { return colorSpace; }
+    GfxColorSpace *getColorSpace() { return colorSpace.get(); }
 
     // Get stream decoding info.
     int getNumPixelComps() const { return nComps; }
@@ -1253,7 +1257,7 @@
 private:
     explicit GfxImageColorMap(const GfxImageColorMap *colorMap);
 
-    GfxColorSpace *colorSpace; // the image color space
+    std::unique_ptr<GfxColorSpace> colorSpace; // the image color space
     int bits; // bits per component
     int nComps; // number of components in a pixel
     GfxColorSpace *colorSpace2; // secondary color space
@@ -1500,8 +1504,8 @@
     void getFillDeviceN(GfxColor *deviceN) { fillColorSpace->getDeviceN(&fillColor, deviceN); }
     void getStrokeCMYK(GfxCMYK *cmyk) { strokeColorSpace->getCMYK(&strokeColor, cmyk); }
     void getStrokeDeviceN(GfxColor *deviceN) { strokeColorSpace->getDeviceN(&strokeColor, deviceN); }
-    GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
-    GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
+    GfxColorSpace *getFillColorSpace() { return fillColorSpace.get(); }
+    GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace.get(); }
     GfxPattern *getFillPattern() { return fillPattern; }
     GfxPattern *getStrokePattern() { return strokePattern; }
     GfxBlendMode getBlendMode() const { return blendMode; }
@@ -1583,8 +1587,8 @@
     void setCTM(double a, double b, double c, double d, double e, double f);
     void concatCTM(double a, double b, double c, double d, double e, double f);
     void shiftCTMAndClip(double tx, double ty);
-    void setFillColorSpace(GfxColorSpace *colorSpace);
-    void setStrokeColorSpace(GfxColorSpace *colorSpace);
+    void setFillColorSpace(std::unique_ptr<GfxColorSpace> &&colorSpace);
+    void setStrokeColorSpace(std::unique_ptr<GfxColorSpace> &&colorSpace);
     void setFillColor(const GfxColor *color) { fillColor = *color; }
     void setStrokeColor(const GfxColor *color) { strokeColor = *color; }
     void setFillPattern(GfxPattern *pattern);
@@ -1631,34 +1635,34 @@
     static GfxLCMSProfilePtr sRGBProfile;
 #endif
 
-    void setDefaultGrayColorSpace(GfxColorSpace *cs) { defaultGrayColorSpace = cs; }
+    void setDefaultGrayColorSpace(std::unique_ptr<GfxColorSpace> &&cs) { defaultGrayColorSpace = std::move(cs); }
 
-    void setDefaultRGBColorSpace(GfxColorSpace *cs) { defaultRGBColorSpace = cs; }
+    void setDefaultRGBColorSpace(std::unique_ptr<GfxColorSpace> &&cs) { defaultRGBColorSpace = std::move(cs); }
 
-    void setDefaultCMYKColorSpace(GfxColorSpace *cs) { defaultCMYKColorSpace = cs; }
+    void setDefaultCMYKColorSpace(std::unique_ptr<GfxColorSpace> &&cs) { defaultCMYKColorSpace = std::move(cs); }
 
-    GfxColorSpace *copyDefaultGrayColorSpace()
+    std::unique_ptr<GfxColorSpace> copyDefaultGrayColorSpace()
     {
         if (defaultGrayColorSpace) {
             return defaultGrayColorSpace->copy();
         }
-        return new GfxDeviceGrayColorSpace();
+        return std::make_unique<GfxDeviceGrayColorSpace>();
     }
 
-    GfxColorSpace *copyDefaultRGBColorSpace()
+    std::unique_ptr<GfxColorSpace> copyDefaultRGBColorSpace()
     {
         if (defaultRGBColorSpace) {
             return defaultRGBColorSpace->copy();
         }
-        return new GfxDeviceRGBColorSpace();
+        return std::make_unique<GfxDeviceRGBColorSpace>();
     }
 
-    GfxColorSpace *copyDefaultCMYKColorSpace()
+    std::unique_ptr<GfxColorSpace> copyDefaultCMYKColorSpace()
     {
         if (defaultCMYKColorSpace) {
             return defaultCMYKColorSpace->copy();
         }
-        return new GfxDeviceCMYKColorSpace();
+        return std::make_unique<GfxDeviceCMYKColorSpace>();
     }
 
     // Add to path.
@@ -1711,8 +1715,8 @@
     double pageWidth, pageHeight; // page size (pixels)
     int rotate; // page rotation angle
 
-    GfxColorSpace *fillColorSpace; // fill color space
-    GfxColorSpace *strokeColorSpace; // stroke color space
+    std::unique_ptr<GfxColorSpace> fillColorSpace; // fill color space
+    std::unique_ptr<GfxColorSpace> strokeColorSpace; // stroke color space
     GfxColor fillColor; // fill color
     GfxColor strokeColor; // stroke color
     GfxPattern *fillPattern; // fill pattern
@@ -1770,9 +1774,9 @@
     static GfxLCMSProfilePtr XYZProfile;
 #endif
 
-    GfxColorSpace *defaultGrayColorSpace;
-    GfxColorSpace *defaultRGBColorSpace;
-    GfxColorSpace *defaultCMYKColorSpace;
+    std::unique_ptr<GfxColorSpace> defaultGrayColorSpace;
+    std::unique_ptr<GfxColorSpace> defaultRGBColorSpace;
+    std::unique_ptr<GfxColorSpace> defaultCMYKColorSpace;
 };
 
 #endif
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index 35ab9bc..1287d22 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -19,7 +19,7 @@
 // Copyright (C) 2007, 2011, 2017, 2021, 2023 Adrian Johnson <ajohnson@redneon.com>
 // Copyright (C) 2009-2013, 2015 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
-// Copyright (C) 2009, 2012, 2013, 2018, 2019, 2021 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2009, 2012, 2013, 2018, 2019, 2021, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2012 William Bader <williambader@hotmail.com>
@@ -142,27 +142,27 @@
 
         auto invalidref = Ref::INVALID();
         if (defaultGrayProfile) {
-            auto cs = new GfxICCBasedColorSpace(1, new GfxDeviceGrayColorSpace(), &invalidref);
+            auto cs = std::make_unique<GfxICCBasedColorSpace>(1, std::make_unique<GfxDeviceGrayColorSpace>(), &invalidref);
 
             cs->setProfile(defaultGrayProfile);
             cs->buildTransforms(state); // needs to happen after state->setDisplayProfile has been called
-            state->setDefaultGrayColorSpace(cs);
+            state->setDefaultGrayColorSpace(std::move(cs));
         }
 
         if (defaultRGBProfile) {
-            auto cs = new GfxICCBasedColorSpace(3, new GfxDeviceRGBColorSpace(), &invalidref);
+            auto cs = std::make_unique<GfxICCBasedColorSpace>(3, std::make_unique<GfxDeviceRGBColorSpace>(), &invalidref);
 
             cs->setProfile(defaultRGBProfile);
             cs->buildTransforms(state); // needs to happen after state->setDisplayProfile has been called
-            state->setDefaultRGBColorSpace(cs);
+            state->setDefaultRGBColorSpace(std::move(cs));
         }
 
         if (defaultCMYKProfile) {
-            auto cs = new GfxICCBasedColorSpace(4, new GfxDeviceCMYKColorSpace(), &invalidref);
+            auto cs = std::make_unique<GfxICCBasedColorSpace>(4, std::make_unique<GfxDeviceCMYKColorSpace>(), &invalidref);
 
             cs->setProfile(defaultCMYKProfile);
             cs->buildTransforms(state); // needs to happen after state->setDisplayProfile has been called
-            state->setDefaultCMYKColorSpace(cs);
+            state->setDefaultCMYKColorSpace(std::move(cs));
         }
 #endif
     }
diff --git a/poppler/Page.cc b/poppler/Page.cc
index d871110..6b441d8 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
-// Copyright (C) 2005-2013, 2016-2023 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005-2013, 2016-2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006-2008 Pino Toscano <pino@kde.org>
 // Copyright (C) 2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
 // Copyright (C) 2006 Scott Turner <scotty1024@mac.com>
@@ -636,7 +636,6 @@
     int width, height, bits;
     Object obj1;
     Dict *dict;
-    GfxColorSpace *colorSpace;
     Stream *str;
     GfxImageColorMap *colorMap;
 
@@ -678,7 +677,7 @@
     // This will set a sRGB profile for ICC-based colorspaces.
     auto pdfrectangle = std::make_shared<PDFRectangle>();
     auto state = std::make_shared<GfxState>(72.0, 72.0, pdfrectangle.get(), 0, false);
-    colorSpace = GfxColorSpace::parse(nullptr, &obj1, nullptr, state.get());
+    std::unique_ptr<GfxColorSpace> colorSpace = GfxColorSpace::parse(nullptr, &obj1, nullptr, state.get());
     if (!colorSpace) {
         fprintf(stderr, "Error: Cannot parse color space\n");
         return false;
@@ -688,7 +687,7 @@
     if (obj1.isNull()) {
         obj1 = dict->lookup("D");
     }
-    colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
+    colorMap = new GfxImageColorMap(bits, &obj1, std::move(colorSpace));
     if (!colorMap->isOk()) {
         fprintf(stderr, "Error: invalid colormap\n");
         delete colorMap;
diff --git a/poppler/PopplerCache.h b/poppler/PopplerCache.h
index 68db153..b291309 100644
--- a/poppler/PopplerCache.h
+++ b/poppler/PopplerCache.h
@@ -5,7 +5,7 @@
 // This file is licensed under the GPLv2 or later
 //
 // Copyright (C) 2009 Koji Otani <sho@bbr.jp>
-// Copyright (C) 2009, 2010, 2017, 2018, 2021 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2009, 2010, 2017, 2018, 2021, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
 //
@@ -58,6 +58,16 @@
         entries.emplace(entries.begin(), key, std::unique_ptr<Item> { item });
     }
 
+    /* The key and item pointers ownership is taken by the cache */
+    void put(const Key &key, std::unique_ptr<Item> &&item)
+    {
+        if (entries.size() == entries.capacity()) {
+            entries.pop_back();
+        }
+
+        entries.emplace(entries.begin(), key, std::move(item));
+    }
+
 private:
     std::vector<std::pair<Key, std::unique_ptr<Item>>> entries;
 };
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 1aa1b2f..83ed0a4 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -3539,7 +3539,7 @@
         Object maskDecode(new Array((xref) ? xref : doc->getXRef()));
         maskDecode.arrayAdd(Object(maskInvert ? 0 : 1));
         maskDecode.arrayAdd(Object(maskInvert ? 1 : 0));
-        maskColorMap = new GfxImageColorMap(1, &maskDecode, new GfxDeviceGrayColorSpace());
+        maskColorMap = new GfxImageColorMap(1, &maskDecode, std::make_unique<GfxDeviceGrayColorSpace>());
         drawSoftMaskedImage(state, ref, str, width, height, colorMap, interpolate, maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate);
         delete maskColorMap;
 
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index 471bdce..aa2d835 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -4692,7 +4692,7 @@
     out->startPage(0, state, nullptr);
     out->setDefaultCTM(state->getCTM());
 
-    state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+    state->setFillColorSpace(std::make_unique<GfxDeviceRGBColorSpace>());
     state->setFillColor(box_color);
     out->updateFillColor(state);
 }
diff --git a/splash/Splash.cc b/splash/Splash.cc
index 86cae28..8f20733 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -5157,7 +5157,7 @@
 
     if (src->getSeparationList()->size() > bitmap->getSeparationList()->size()) {
         for (x = bitmap->getSeparationList()->size(); x < (int)src->getSeparationList()->size(); x++) {
-            bitmap->getSeparationList()->push_back((GfxSeparationColorSpace *)((*src->getSeparationList())[x])->copy());
+            bitmap->getSeparationList()->push_back(((*src->getSeparationList())[x])->copyAsOwnType());
         }
     }
     if (src->alpha) {
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index af4a622..8896102 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -11,7 +11,7 @@
 // All changes made under the Poppler project to this file are licensed
 // under GPL version 2 or later
 //
-// Copyright (C) 2006, 2009, 2010, 2012, 2015, 2018, 2019, 2021, 2022 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2006, 2009, 2010, 2012, 2015, 2018, 2019, 2021, 2022, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2007 Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
 // Copyright (C) 2009 Shen Liang <shenzhuxi@gmail.com>
 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
@@ -53,7 +53,7 @@
 // SplashBitmap
 //------------------------------------------------------------------------
 
-SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPadA, SplashColorMode modeA, bool alphaA, bool topDown, const std::vector<GfxSeparationColorSpace *> *separationListA)
+SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPadA, SplashColorMode modeA, bool alphaA, bool topDown, const std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationListA)
 {
     width = widthA;
     height = heightA;
@@ -122,10 +122,10 @@
     } else {
         alpha = nullptr;
     }
-    separationList = new std::vector<GfxSeparationColorSpace *>();
+    separationList = new std::vector<std::unique_ptr<GfxSeparationColorSpace>>();
     if (separationListA != nullptr) {
-        for (const GfxSeparationColorSpace *separation : *separationListA) {
-            separationList->push_back((GfxSeparationColorSpace *)separation->copy());
+        for (const std::unique_ptr<GfxSeparationColorSpace> &separation : *separationListA) {
+            separationList->push_back(separation->copyAsOwnType());
         }
     }
 }
@@ -160,9 +160,6 @@
         }
     }
     gfree(alpha);
-    for (auto entry : *separationList) {
-        delete entry;
-    }
     delete separationList;
 }
 
@@ -453,7 +450,7 @@
                     GfxCMYK cmyk;
                     GfxColor input;
                     input.c[0] = byteToCol(col[i + 4]);
-                    GfxSeparationColorSpace *sepCS = (GfxSeparationColorSpace *)((*separationList)[i]);
+                    const std::unique_ptr<GfxSeparationColorSpace> &sepCS = (*separationList)[i];
                     sepCS->getCMYK(&input, &cmyk);
                     col[0] = colToByte(cmyk.c);
                     col[1] = colToByte(cmyk.m);
@@ -506,7 +503,7 @@
                     GfxCMYK cmyk;
                     GfxColor input;
                     input.c[0] = byteToCol(col[i + 4]);
-                    GfxSeparationColorSpace *sepCS = (GfxSeparationColorSpace *)((*separationList)[i]);
+                    const std::unique_ptr<GfxSeparationColorSpace> &sepCS = (*separationList)[i];
                     sepCS->getCMYK(&input, &cmyk);
                     col[0] = colToByte(cmyk.c);
                     col[1] = colToByte(cmyk.m);
@@ -629,7 +626,7 @@
                     GfxCMYK cmyk;
                     GfxColor input;
                     input.c[0] = byteToCol(col[i + 4]);
-                    GfxSeparationColorSpace *sepCS = (GfxSeparationColorSpace *)((*separationList)[i]);
+                    const std::unique_ptr<GfxSeparationColorSpace> &sepCS = (*separationList)[i];
                     sepCS->getCMYK(&input, &cmyk);
                     col[0] = colToByte(cmyk.c);
                     col[1] = colToByte(cmyk.m);
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index 2d7cf41..367d9fe 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2007 Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
 // Copyright (C) 2009 Shen Liang <shenzhuxi@gmail.com>
-// Copyright (C) 2009, 2012, 2018, 2021, 2022 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2009, 2012, 2018, 2021, 2022, 2024 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
 // Copyright (C) 2010, 2017 Adrian Johnson <ajohnson@redneon.com>
 // Copyright (C) 2010 Harry Roberts <harry.roberts@midnight-labs.org>
@@ -36,6 +36,7 @@
 #include "SplashTypes.h"
 #include "poppler_private_export.h"
 #include <cstdio>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -53,7 +54,7 @@
     // color mode <modeA>.  Rows will be padded out to a multiple of
     // <rowPad> bytes.  If <topDown> is false, the bitmap will be stored
     // upside-down, i.e., with the last row first in memory.
-    SplashBitmap(int widthA, int heightA, int rowPad, SplashColorMode modeA, bool alphaA, bool topDown = true, const std::vector<GfxSeparationColorSpace *> *separationList = nullptr);
+    SplashBitmap(int widthA, int heightA, int rowPad, SplashColorMode modeA, bool alphaA, bool topDown = true, const std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList = nullptr);
     static SplashBitmap *copy(const SplashBitmap *src);
 
     ~SplashBitmap();
@@ -69,10 +70,10 @@
     SplashColorMode getMode() const { return mode; }
     SplashColorPtr getDataPtr() { return data; }
     unsigned char *getAlphaPtr() { return alpha; }
-    std::vector<GfxSeparationColorSpace *> *getSeparationList() { return separationList; }
+    std::vector<std::unique_ptr<GfxSeparationColorSpace>> *getSeparationList() { return separationList; }
     SplashColorConstPtr getDataPtr() const { return data; }
     const unsigned char *getAlphaPtr() const { return alpha; }
-    const std::vector<GfxSeparationColorSpace *> *getSeparationList() const { return separationList; }
+    const std::vector<std::unique_ptr<GfxSeparationColorSpace>> *getSeparationList() const { return separationList; }
 
     SplashError writePNMFile(char *fileName);
     SplashError writePNMFile(FILE *f);
@@ -119,7 +120,7 @@
     SplashColorPtr data; // pointer to row zero of the color data
     unsigned char *alpha; // pointer to row zero of the alpha data
                           //   (always top-down)
-    std::vector<GfxSeparationColorSpace *> *separationList; // list of spot colorants and their mapping functions
+    std::vector<std::unique_ptr<GfxSeparationColorSpace>> *separationList; // list of spot colorants and their mapping functions
 
     friend class Splash;