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