@@ -467,10 +467,20 @@ def _convert_to_py_string(value) -> str:
467467 if value is None :
468468 return ""
469469
470- # Convert to Python string and free the Rust-allocated memory
471- py_string = ctypes .cast (value , ctypes .c_char_p ).value .decode ('utf-8' )
472- _lib .c2pa_string_free (value )
470+ py_string = ""
471+ ptr = ctypes .cast (value , ctypes .c_char_p )
473472
473+ # Only if we got a valid pointer
474+ if ptr and ptr .value is not None :
475+ try :
476+ py_string = ptr .value .decode ('utf-8' , errors = 'replace' )
477+ except Exception :
478+ py_string = ""
479+
480+ # Free the Rust-allocated memory
481+ _lib .c2pa_string_free (value )
482+
483+ # In case of invalid pointer, no free (avoids double-free)
474484 return py_string
475485
476486
@@ -1407,7 +1417,7 @@ def resource_to_stream(self, uri: str, stream: Any) -> int:
14071417 The number of bytes written
14081418
14091419 Raises:
1410- C2paError: If there was an error writing the resource
1420+ C2paError: If there was an error writing the resource to stream
14111421 """
14121422 if not self ._reader :
14131423 raise C2paError ("Reader is closed" )
@@ -1453,6 +1463,9 @@ def __init__(self, signer_ptr: ctypes.POINTER(C2paSigner)):
14531463 self ._signer = signer_ptr
14541464 self ._closed = False
14551465
1466+ # Set only for signers which are callback signers
1467+ self ._callback_cb = None
1468+
14561469 @classmethod
14571470 def from_info (cls , signer_info : C2paSignerInfo ) -> 'Signer' :
14581471 """Create a new Signer from signer information.
0 commit comments