Untitled

Anonymous
plain_text
02/16/2026 6:42 AM
14.0 KB
15
Indexable
--- /tmp/Img-2.1.0/jpeg/jpeg.c	2025-03-22 04:14:27.000000000 +0400
+++ /home/archie/.local/src/Img-2.1.0/jpeg/jpeg.c	2026-02-16 10:32:18.211035696 +0400
@@ -475,6 +475,78 @@
     return retVal;
 }
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * jpegTryBase64Decode --
+ *
+ *      Check if dataObj contains base64-encoded JPEG data rather than
+ *      raw binary. Tk 9.0 Version3 format handlers receive base64
+ *      data as-is (not pre-decoded) in the stringMatchProc.
+ *
+ * Results:
+ *      Returns a new Tcl_Obj with decoded binary data (refcount 1)
+ *      if base64 decoding was needed and successful.
+ *      Returns NULL if the data is already raw binary JPEG or
+ *      if decoding fails.
+ *
+ *----------------------------------------------------------------------
+ */
+static Tcl_Obj *jpegTryBase64Decode(
+    Tcl_Interp *interp,
+    Tcl_Obj *dataObj
+) {
+    const unsigned char *bytes;
+    Tcl_Size length;
+    Tcl_Obj *cmdv[4], *resultObj;
+
+    bytes = Tcl_GetByteArrayFromObj(dataObj, &length);
+    if (bytes == NULL || length < 2) {
+        return NULL;
+    }
+
+    /* Already raw JPEG binary data (starts with SOI marker). */
+    if (bytes[0] == 0xFF && bytes[1] == 0xD8) {
+        return NULL;
+    }
+
+    /* Try base64 decode: [binary decode base64 $dataObj] */
+    cmdv[0] = Tcl_NewStringObj("binary", -1);
+    cmdv[1] = Tcl_NewStringObj("decode", -1);
+    cmdv[2] = Tcl_NewStringObj("base64", -1);
+    cmdv[3] = Tcl_DuplicateObj(dataObj);
+
+    Tcl_IncrRefCount(cmdv[0]);
+    Tcl_IncrRefCount(cmdv[1]);
+    Tcl_IncrRefCount(cmdv[2]);
+    Tcl_IncrRefCount(cmdv[3]);
+
+    if (Tcl_EvalObjv(interp, 4, cmdv, TCL_EVAL_DIRECT) != TCL_OK) {
+        Tcl_DecrRefCount(cmdv[0]);
+        Tcl_DecrRefCount(cmdv[1]);
+        Tcl_DecrRefCount(cmdv[2]);
+        Tcl_DecrRefCount(cmdv[3]);
+        Tcl_ResetResult(interp);
+        return NULL;
+    }
+
+    Tcl_DecrRefCount(cmdv[0]);
+    Tcl_DecrRefCount(cmdv[1]);
+    Tcl_DecrRefCount(cmdv[2]);
+    Tcl_DecrRefCount(cmdv[3]);
+
+    resultObj = Tcl_GetObjResult(interp);
+    bytes = Tcl_GetByteArrayFromObj(resultObj, &length);
+    if (bytes == NULL || length < 2 || bytes[0] != 0xFF || bytes[1] != 0xD8) {
+        Tcl_ResetResult(interp);
+        return NULL;
+    }
+
+    Tcl_IncrRefCount(resultObj);
+    Tcl_ResetResult(interp);
+    return resultObj;
+}
+
 static int StringMatchVersion3(
     Tcl_Interp *interp,
     Tcl_Obj *dataObj,
@@ -488,8 +560,16 @@
     struct jpeg_decompress_struct cinfo; /* libjpeg's parameter structure */
     struct my_error_mgr jerror; /* for controlling libjpeg error handling */
     tkimg_Stream handle;
+    Tcl_Obj *decodedObj = NULL;
     memset(&handle, 0, sizeof (tkimg_Stream));
 
+    /* Try base64 decode for Tk 9.0 Version3 format handler compatibility.
+     * Must be called before SETJMP so decodedObj is safe in longjmp. */
+    decodedObj = jpegTryBase64Decode(interp, dataObj);
+    if (decodedObj != NULL) {
+        dataObj = decodedObj;
+    }
+
     /* Initialize JPEG error handler */
     /* We set up the normal JPEG error routines, then override error_exit. */
     cinfo.err = jpeg_std_error(&jerror.pub);
@@ -500,6 +580,9 @@
     if (SETJMP(jerror.setjmp_buffer)) {
       /* If we get here, the JPEG code has signaled an error. */
       jpeg_destroy_decompress(&cinfo);
+      if (decodedObj != NULL) {
+          Tcl_DecrRefCount(decodedObj);
+      }
       return 0;
     }
 
@@ -509,11 +592,17 @@
     my_jpeg_obj_src(&cinfo, dataObj);
 
     if (!tkimg_ReadInitString(&handle, dataObj)) {
+        if (decodedObj != NULL) {
+            Tcl_DecrRefCount(decodedObj);
+        }
         return 0;
     }
     retVal = CommonMatch(&cinfo, &handle, widthPtr, heightPtr, &xdpi, &ydpi);
     if (retVal && xdpi >= 0.0 && ydpi >= 0.0) {
         if (TCL_ERROR == tkimg_SetResolution( metadataOut, xdpi, ydpi)) {
+            if (decodedObj != NULL) {
+                Tcl_DecrRefCount(decodedObj);
+            }
             return 0;
         }
     }
@@ -521,6 +610,9 @@
     /* Reclaim libjpeg's internal resources. */
     jpeg_destroy_decompress(&cinfo);
 
+    if (decodedObj != NULL) {
+        Tcl_DecrRefCount(decodedObj);
+    }
     return retVal;
 }
 
@@ -706,6 +798,14 @@
     struct jpeg_decompress_struct cinfo; /* libjpeg's parameter structure */
     struct my_error_mgr jerror; /* for controlling libjpeg error handling */
     int result;
+    Tcl_Obj *decodedObj = NULL;
+
+    /* Try base64 decode for Tk 9.0 Version3 format handler compatibility.
+     * Must be called before SETJMP so decodedObj is safe in longjmp. */
+    decodedObj = jpegTryBase64Decode(interp, dataObj);
+    if (decodedObj != NULL) {
+        dataObj = decodedObj;
+    }
 
     /* Initialize JPEG error handler */
     /* We set up the normal JPEG error routines, then override error_exit. */
@@ -719,6 +819,9 @@
       Tcl_AppendResult(interp, "Could not read JPEG string: ", (char *) NULL);
       append_jpeg_message(interp, (j_common_ptr) &cinfo);
       jpeg_destroy_decompress(&cinfo);
+      if (decodedObj != NULL) {
+          Tcl_DecrRefCount(decodedObj);
+      }
       return TCL_ERROR;
     }
 
@@ -735,6 +838,9 @@
     /* Reclaim libjpeg's internal resources. */
     jpeg_destroy_decompress(&cinfo);
 
+    if (decodedObj != NULL) {
+        Tcl_DecrRefCount(decodedObj);
+    }
     return result;
 }
 
--- /tmp/Img-2.1.0/png/png.c	2025-03-22 04:14:38.000000000 +0400
+++ /home/archie/.local/src/Img-2.1.0/png/png.c	2026-02-16 10:32:19.115035706 +0400
@@ -444,6 +444,82 @@
     return retVal;
 }
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * pngTryBase64Decode --
+ *
+ *      Check if dataObj contains base64-encoded PNG data rather than
+ *      raw binary. Tk 9.0 Version3 format handlers receive base64
+ *      data as-is (not pre-decoded) in the stringMatchProc.
+ *
+ * Results:
+ *      Returns a new Tcl_Obj with decoded binary data (refcount 1)
+ *      if base64 decoding was needed and successful.
+ *      Returns NULL if the data is already raw binary PNG or
+ *      if decoding fails.
+ *
+ *----------------------------------------------------------------------
+ */
+static Tcl_Obj *pngTryBase64Decode(
+    Tcl_Interp *interp,
+    Tcl_Obj *dataObj
+) {
+    const unsigned char *bytes;
+    Tcl_Size length;
+    Tcl_Obj *cmdv[4], *resultObj;
+    /* PNG signature: 89 50 4E 47 0D 0A 1A 0A */
+    static const unsigned char pngSig[8] = {
+        0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
+    };
+
+    bytes = Tcl_GetByteArrayFromObj(dataObj, &length);
+    if (bytes == NULL || length < 8) {
+        return NULL;
+    }
+
+    /* Already raw PNG binary data (starts with PNG signature). */
+    if (memcmp(bytes, pngSig, 8) == 0) {
+        return NULL;
+    }
+
+    /* Try base64 decode: [binary decode base64 $dataObj] */
+    cmdv[0] = Tcl_NewStringObj("binary", -1);
+    cmdv[1] = Tcl_NewStringObj("decode", -1);
+    cmdv[2] = Tcl_NewStringObj("base64", -1);
+    cmdv[3] = Tcl_DuplicateObj(dataObj);
+
+    Tcl_IncrRefCount(cmdv[0]);
+    Tcl_IncrRefCount(cmdv[1]);
+    Tcl_IncrRefCount(cmdv[2]);
+    Tcl_IncrRefCount(cmdv[3]);
+
+    if (Tcl_EvalObjv(interp, 4, cmdv, TCL_EVAL_DIRECT) != TCL_OK) {
+        Tcl_DecrRefCount(cmdv[0]);
+        Tcl_DecrRefCount(cmdv[1]);
+        Tcl_DecrRefCount(cmdv[2]);
+        Tcl_DecrRefCount(cmdv[3]);
+        Tcl_ResetResult(interp);
+        return NULL;
+    }
+
+    Tcl_DecrRefCount(cmdv[0]);
+    Tcl_DecrRefCount(cmdv[1]);
+    Tcl_DecrRefCount(cmdv[2]);
+    Tcl_DecrRefCount(cmdv[3]);
+
+    resultObj = Tcl_GetObjResult(interp);
+    bytes = Tcl_GetByteArrayFromObj(resultObj, &length);
+    if (bytes == NULL || length < 8 || memcmp(bytes, pngSig, 8) != 0) {
+        Tcl_ResetResult(interp);
+        return NULL;
+    }
+
+    Tcl_IncrRefCount(resultObj);
+    Tcl_ResetResult(interp);
+    return resultObj;
+}
+
 static int StringMatchVersion3(
     Tcl_Interp *interp,
     Tcl_Obj *dataObj,
@@ -457,18 +533,31 @@
     int retVal;
     double xdpi, ydpi;
     tkimg_Stream handle;
+    Tcl_Obj *decodedObj = NULL;
     memset(&handle, 0, sizeof (tkimg_Stream));
 
+    /* Try base64 decode for Tk 9.0 Version3 format handler compatibility. */
+    decodedObj = pngTryBase64Decode(interp, dataObj);
+    if (decodedObj != NULL) {
+        dataObj = decodedObj;
+    }
+
     cleanup.interp = interp;
 
     png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,
             (png_voidp) &cleanup, tk_png_error, tk_png_warning);
     if (!png_ptr) {
+        if (decodedObj != NULL) {
+            Tcl_DecrRefCount(decodedObj);
+        }
         return 0;
     }
 
     if (!tkimg_ReadInitString(&handle, dataObj)) {
         png_destroy_read_struct(&png_ptr, NULL, NULL);
+        if (decodedObj != NULL) {
+            Tcl_DecrRefCount(decodedObj);
+        }
         return 0;
     }
 
@@ -477,9 +566,15 @@
     retVal = CommonMatch(png_ptr, &handle, widthPtr, heightPtr, &xdpi, &ydpi);
     if (retVal && xdpi >= 0.0 && ydpi >= 0.0) {
         if (TCL_ERROR == tkimg_SetResolution(metadataOut, xdpi, ydpi)) {
+            if (decodedObj != NULL) {
+                Tcl_DecrRefCount(decodedObj);
+            }
             return 0;
         }
     }
+    if (decodedObj != NULL) {
+        Tcl_DecrRefCount(decodedObj);
+    }
     return retVal;
 }
 
@@ -606,22 +701,42 @@
     png_structp png_ptr;
     cleanup_info cleanup;
     tkimg_Stream handle;
+    Tcl_Obj *decodedObj = NULL;
+    int result;
     memset(&handle, 0, sizeof (tkimg_Stream));
 
+    /* Try base64 decode for Tk 9.0 Version3 format handler compatibility. */
+    decodedObj = pngTryBase64Decode(interp, dataObj);
+    if (decodedObj != NULL) {
+        dataObj = decodedObj;
+    }
+
     cleanup.interp = interp;
 
     png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,
             (png_voidp) &cleanup,tk_png_error,tk_png_warning);
-    if (!png_ptr) return TCL_ERROR;
+    if (!png_ptr) {
+        if (decodedObj != NULL) {
+            Tcl_DecrRefCount(decodedObj);
+        }
+        return TCL_ERROR;
+    }
 
     if (!tkimg_ReadInitString(&handle, dataObj)) {
+        if (decodedObj != NULL) {
+            Tcl_DecrRefCount(decodedObj);
+        }
         return 0;
     }
 
     png_set_read_fn(png_ptr,(png_voidp) &handle, tk_png_read);
 
-    return CommonRead(png_ptr, interp, "InlineData", format, imageHandle, destX, destY,
+    result = CommonRead(png_ptr, interp, "InlineData", format, imageHandle, destX, destY,
             width, height, srcX, srcY, metadataOut);
+    if (decodedObj != NULL) {
+        Tcl_DecrRefCount(decodedObj);
+    }
+    return result;
 }
 
 #if HAVE_FORMAT_VERSION3 == 0
Editor is loading...
Leave a Comment