Store avifColourInformationBox.iccOffset, not ptr

Fix mem issue in avifParseColourInformationBox().
diff --git a/src/read.c b/src/read.c
index 71ba7fe..56b4329 100644
--- a/src/read.c
+++ b/src/read.c
@@ -75,7 +75,7 @@
 typedef struct avifColourInformationBox
 {
     avifBool hasICC;
-    const uint8_t * icc;
+    uint64_t iccOffset;
     size_t iccSize;
 
     avifBool hasNCLX;
@@ -1728,7 +1728,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseColourInformationBox(avifProperty * prop, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseColourInformationBox(avifProperty * prop, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
 {
     BEGIN_STREAM(s, raw, rawLen, diag, "Box[colr]");
 
@@ -1740,7 +1740,10 @@
     AVIF_CHECK(avifROStreamRead(&s, colorType, 4));
     if (!memcmp(colorType, "rICC", 4) || !memcmp(colorType, "prof", 4)) {
         colr->hasICC = AVIF_TRUE;
-        colr->icc = avifROStreamCurrent(&s);
+        // Remember the offset of the ICC payload relative to the beginning of the stream. A direct pointer cannot be stored
+        // because decoder->io->persistent could have been AVIF_FALSE when obtaining raw through decoder->io->read().
+        // The bytes could be copied now instead of remembering the offset, but it is as invasive as passing rawOffset everywhere.
+        colr->iccOffset = rawOffset + avifROStreamOffset(&s);
         colr->iccSize = avifROStreamRemainingBytes(&s);
     } else if (!memcmp(colorType, "nclx", 4)) {
         AVIF_CHECK(avifROStreamReadU16(&s, &colr->colorPrimaries));          // unsigned int(16) colour_primaries;
@@ -1914,7 +1917,11 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemPropertyContainerBox(avifPropertyArray * properties, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseItemPropertyContainerBox(avifPropertyArray * properties,
+                                                  uint64_t rawOffset,
+                                                  const uint8_t * raw,
+                                                  size_t rawLen,
+                                                  avifDiagnostics * diag)
 {
     BEGIN_STREAM(s, raw, rawLen, diag, "Box[ipco]");
 
@@ -1930,7 +1937,7 @@
         } else if (!memcmp(header.type, "auxC", 4)) {
             AVIF_CHECK(avifParseAuxiliaryTypeProperty(prop, avifROStreamCurrent(&s), header.size, diag));
         } else if (!memcmp(header.type, "colr", 4)) {
-            AVIF_CHECK(avifParseColourInformationBox(prop, avifROStreamCurrent(&s), header.size, diag));
+            AVIF_CHECK(avifParseColourInformationBox(prop, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), header.size, diag));
         } else if (!memcmp(header.type, "av1C", 4)) {
             AVIF_CHECK(avifParseAV1CodecConfigurationBoxProperty(prop, avifROStreamCurrent(&s), header.size, diag));
         } else if (!memcmp(header.type, "pasp", 4)) {
@@ -2145,7 +2152,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseItemPropertiesBox(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseItemPropertiesBox(avifMeta * meta, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
 {
     BEGIN_STREAM(s, raw, rawLen, diag, "Box[iprp]");
 
@@ -2157,7 +2164,11 @@
     }
 
     // Read all item properties inside of ItemPropertyContainerBox
-    AVIF_CHECK(avifParseItemPropertyContainerBox(&meta->properties, avifROStreamCurrent(&s), ipcoHeader.size, diag));
+    AVIF_CHECK(avifParseItemPropertyContainerBox(&meta->properties,
+                                                 rawOffset + avifROStreamOffset(&s),
+                                                 avifROStreamCurrent(&s),
+                                                 ipcoHeader.size,
+                                                 diag));
     AVIF_CHECK(avifROStreamSkip(&s, ipcoHeader.size));
 
     uint32_t versionAndFlagsSeen[MAX_IPMA_VERSION_AND_FLAGS_SEEN];
@@ -2362,7 +2373,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMetaBox(avifMeta * meta, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseMetaBox(avifMeta * meta, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
 {
     BEGIN_STREAM(s, raw, rawLen, diag, "Box[meta]");
 
@@ -2397,7 +2408,7 @@
             AVIF_CHECK(avifParseItemDataBox(meta, avifROStreamCurrent(&s), header.size, diag));
         } else if (!memcmp(header.type, "iprp", 4)) {
             AVIF_CHECK(uniqueBoxSeen(&uniqueBoxFlags, 4, "meta", "iprp", diag));
-            AVIF_CHECK(avifParseItemPropertiesBox(meta, avifROStreamCurrent(&s), header.size, diag));
+            AVIF_CHECK(avifParseItemPropertiesBox(meta, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), header.size, diag));
         } else if (!memcmp(header.type, "iinf", 4)) {
             AVIF_CHECK(uniqueBoxSeen(&uniqueBoxFlags, 5, "meta", "iinf", diag));
             AVIF_CHECK(avifParseItemInfoBox(meta, avifROStreamCurrent(&s), header.size, diag));
@@ -2621,7 +2632,11 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseSampleDescriptionBox(avifSampleTable * sampleTable, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseSampleDescriptionBox(avifSampleTable * sampleTable,
+                                              uint64_t rawOffset,
+                                              const uint8_t * raw,
+                                              size_t rawLen,
+                                              avifDiagnostics * diag)
 {
     BEGIN_STREAM(s, raw, rawLen, diag, "Box[stsd]");
 
@@ -2643,6 +2658,7 @@
         size_t remainingBytes = avifROStreamRemainingBytes(&s);
         if (!memcmp(description->format, "av01", 4) && (remainingBytes > VISUALSAMPLEENTRY_SIZE)) {
             AVIF_CHECK(avifParseItemPropertyContainerBox(&description->properties,
+                                                         rawOffset + avifROStreamOffset(&s) + VISUALSAMPLEENTRY_SIZE,
                                                          avifROStreamCurrent(&s) + VISUALSAMPLEENTRY_SIZE,
                                                          remainingBytes - VISUALSAMPLEENTRY_SIZE,
                                                          diag));
@@ -2653,7 +2669,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseSampleTableBox(avifTrack * track, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseSampleTableBox(avifTrack * track, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
 {
     if (track->sampleTable) {
         // A TrackBox may only have one SampleTable
@@ -2681,7 +2697,11 @@
         } else if (!memcmp(header.type, "stts", 4)) {
             AVIF_CHECK(avifParseTimeToSampleBox(track->sampleTable, avifROStreamCurrent(&s), header.size, diag));
         } else if (!memcmp(header.type, "stsd", 4)) {
-            AVIF_CHECK(avifParseSampleDescriptionBox(track->sampleTable, avifROStreamCurrent(&s), header.size, diag));
+            AVIF_CHECK(avifParseSampleDescriptionBox(track->sampleTable,
+                                                     rawOffset + avifROStreamOffset(&s),
+                                                     avifROStreamCurrent(&s),
+                                                     header.size,
+                                                     diag));
         }
 
         AVIF_CHECK(avifROStreamSkip(&s, header.size));
@@ -2689,7 +2709,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMediaInformationBox(avifTrack * track, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseMediaInformationBox(avifTrack * track, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
 {
     BEGIN_STREAM(s, raw, rawLen, diag, "Box[minf]");
 
@@ -2698,7 +2718,7 @@
         AVIF_CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "stbl", 4)) {
-            AVIF_CHECK(avifParseSampleTableBox(track, avifROStreamCurrent(&s), header.size, diag));
+            AVIF_CHECK(avifParseSampleTableBox(track, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), header.size, diag));
         }
 
         AVIF_CHECK(avifROStreamSkip(&s, header.size));
@@ -2706,7 +2726,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMediaBox(avifTrack * track, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
+static avifBool avifParseMediaBox(avifTrack * track, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, avifDiagnostics * diag)
 {
     BEGIN_STREAM(s, raw, rawLen, diag, "Box[mdia]");
 
@@ -2717,7 +2737,7 @@
         if (!memcmp(header.type, "mdhd", 4)) {
             AVIF_CHECK(avifParseMediaHeaderBox(track, avifROStreamCurrent(&s), header.size, diag));
         } else if (!memcmp(header.type, "minf", 4)) {
-            AVIF_CHECK(avifParseMediaInformationBox(track, avifROStreamCurrent(&s), header.size, diag));
+            AVIF_CHECK(avifParseMediaInformationBox(track, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), header.size, diag));
         }
 
         AVIF_CHECK(avifROStreamSkip(&s, header.size));
@@ -2750,7 +2770,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseTrackBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen, uint32_t imageSizeLimit, uint32_t imageDimensionLimit)
+static avifBool avifParseTrackBox(avifDecoderData * data, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, uint32_t imageSizeLimit, uint32_t imageDimensionLimit)
 {
     BEGIN_STREAM(s, raw, rawLen, data->diag, "Box[trak]");
 
@@ -2763,9 +2783,9 @@
         if (!memcmp(header.type, "tkhd", 4)) {
             AVIF_CHECK(avifParseTrackHeaderBox(track, avifROStreamCurrent(&s), header.size, imageSizeLimit, imageDimensionLimit, data->diag));
         } else if (!memcmp(header.type, "meta", 4)) {
-            AVIF_CHECK(avifParseMetaBox(track->meta, avifROStreamCurrent(&s), header.size, data->diag));
+            AVIF_CHECK(avifParseMetaBox(track->meta, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), header.size, data->diag));
         } else if (!memcmp(header.type, "mdia", 4)) {
-            AVIF_CHECK(avifParseMediaBox(track, avifROStreamCurrent(&s), header.size, data->diag));
+            AVIF_CHECK(avifParseMediaBox(track, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), header.size, data->diag));
         } else if (!memcmp(header.type, "tref", 4)) {
             AVIF_CHECK(avifTrackReferenceBox(track, avifROStreamCurrent(&s), header.size, data->diag));
         }
@@ -2775,7 +2795,7 @@
     return AVIF_TRUE;
 }
 
-static avifBool avifParseMovieBox(avifDecoderData * data, const uint8_t * raw, size_t rawLen, uint32_t imageSizeLimit, uint32_t imageDimensionLimit)
+static avifBool avifParseMovieBox(avifDecoderData * data, uint64_t rawOffset, const uint8_t * raw, size_t rawLen, uint32_t imageSizeLimit, uint32_t imageDimensionLimit)
 {
     BEGIN_STREAM(s, raw, rawLen, data->diag, "Box[moov]");
 
@@ -2784,7 +2804,8 @@
         AVIF_CHECK(avifROStreamReadBoxHeader(&s, &header));
 
         if (!memcmp(header.type, "trak", 4)) {
-            AVIF_CHECK(avifParseTrackBox(data, avifROStreamCurrent(&s), header.size, imageSizeLimit, imageDimensionLimit));
+            AVIF_CHECK(
+                avifParseTrackBox(data, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), header.size, imageSizeLimit, imageDimensionLimit));
         }
 
         AVIF_CHECK(avifROStreamSkip(&s, header.size));
@@ -2852,10 +2873,12 @@
         assert((decoder->io->sizeHint == 0) || (parseOffset <= decoder->io->sizeHint));
 
         // Try to get the remainder of the box, if necessary
+        uint64_t boxOffset = 0;
         avifROData boxContents = AVIF_DATA_EMPTY;
 
         // TODO: reorg this code to only do these memcmps once each
         if (!memcmp(header.type, "ftyp", 4) || !memcmp(header.type, "meta", 4) || !memcmp(header.type, "moov", 4)) {
+            boxOffset = parseOffset;
             readResult = decoder->io->read(decoder->io, 0, parseOffset, header.size, &boxContents);
             if (readResult != AVIF_RESULT_OK) {
                 return readResult;
@@ -2882,11 +2905,12 @@
             needsMoov = avifFileTypeHasBrand(&ftyp, "avis");
         } else if (!memcmp(header.type, "meta", 4)) {
             AVIF_CHECKERR(!metaSeen, AVIF_RESULT_BMFF_PARSE_FAILED);
-            AVIF_CHECKERR(avifParseMetaBox(data->meta, boxContents.data, boxContents.size, data->diag), AVIF_RESULT_BMFF_PARSE_FAILED);
+            AVIF_CHECKERR(avifParseMetaBox(data->meta, boxOffset, boxContents.data, boxContents.size, data->diag),
+                          AVIF_RESULT_BMFF_PARSE_FAILED);
             metaSeen = AVIF_TRUE;
         } else if (!memcmp(header.type, "moov", 4)) {
             AVIF_CHECKERR(!moovSeen, AVIF_RESULT_BMFF_PARSE_FAILED);
-            AVIF_CHECKERR(avifParseMovieBox(data, boxContents.data, boxContents.size, decoder->imageSizeLimit, decoder->imageDimensionLimit),
+            AVIF_CHECKERR(avifParseMovieBox(data, boxOffset, boxContents.data, boxContents.size, decoder->imageSizeLimit, decoder->imageDimensionLimit),
                           AVIF_RESULT_BMFF_PARSE_FAILED);
             moovSeen = AVIF_TRUE;
         }
@@ -3637,8 +3661,13 @@
                 if (colrICCSeen) {
                     return AVIF_RESULT_BMFF_PARSE_FAILED;
                 }
+                avifROData icc;
+                const avifResult readResult = decoder->io->read(decoder->io, 0, prop->u.colr.iccOffset, prop->u.colr.iccSize, &icc);
+                if (readResult != AVIF_RESULT_OK) {
+                    return readResult;
+                }
                 colrICCSeen = AVIF_TRUE;
-                avifImageSetProfileICC(decoder->image, prop->u.colr.icc, prop->u.colr.iccSize);
+                avifImageSetProfileICC(decoder->image, icc.data, icc.size);
             }
             if (prop->u.colr.hasNCLX) {
                 if (colrNCLXSeen) {