@@ -340,8 +340,8 @@ impl LogicalExtensionCodec for PythonLogicalCodec {
340340 if let Some ( udf) = try_decode_python_scalar_udf ( buf) ? {
341341 return Ok ( udf) ;
342342 }
343- } else if buf . starts_with ( PY_SCALAR_UDF_FAMILY ) {
344- return Err ( refuse_inline_payload ( "scalar UDF" , name) ) ;
343+ } else {
344+ refuse_if_inline ( buf , PY_SCALAR_UDF_FAMILY , "scalar UDF" , name) ? ;
345345 }
346346 self . inner . try_decode_udf ( name, buf)
347347 }
@@ -358,8 +358,8 @@ impl LogicalExtensionCodec for PythonLogicalCodec {
358358 if let Some ( udaf) = try_decode_python_udaf ( buf) ? {
359359 return Ok ( udaf) ;
360360 }
361- } else if buf . starts_with ( PY_AGG_UDF_FAMILY ) {
362- return Err ( refuse_inline_payload ( "aggregate UDF" , name) ) ;
361+ } else {
362+ refuse_if_inline ( buf , PY_AGG_UDF_FAMILY , "aggregate UDF" , name) ? ;
363363 }
364364 self . inner . try_decode_udaf ( name, buf)
365365 }
@@ -376,13 +376,30 @@ impl LogicalExtensionCodec for PythonLogicalCodec {
376376 if let Some ( udwf) = try_decode_python_udwf ( buf) ? {
377377 return Ok ( udwf) ;
378378 }
379- } else if buf . starts_with ( PY_WINDOW_UDF_FAMILY ) {
380- return Err ( refuse_inline_payload ( "window UDF" , name) ) ;
379+ } else {
380+ refuse_if_inline ( buf , PY_WINDOW_UDF_FAMILY , "window UDF" , name) ? ;
381381 }
382382 self . inner . try_decode_udwf ( name, buf)
383383 }
384384}
385385
386+ /// Strict-mode gate: if `buf` is a well-framed inline payload for
387+ /// `family`, return the strict-refusal error; otherwise return
388+ /// `Ok(())` so the caller can delegate to its `inner` codec.
389+ ///
390+ /// Routing through [`read_framed_payload`] (rather than a bare
391+ /// `starts_with` probe) means malformed inline bytes — wrong
392+ /// wire-format version, mismatched Python version, truncated header —
393+ /// surface *their* diagnostic instead of the strict-mode message.
394+ /// The strict message implies sender intent ("inlining is disabled"),
395+ /// so it should fire only when the bytes really would have decoded.
396+ fn refuse_if_inline ( buf : & [ u8 ] , family : & [ u8 ] , kind : & str , name : & str ) -> Result < ( ) > {
397+ Python :: attach ( |py| match read_framed_payload ( py, buf, family, kind) ? {
398+ Some ( _) => Err ( refuse_inline_payload ( kind, name) ) ,
399+ None => Ok ( ( ) ) ,
400+ } )
401+ }
402+
386403/// Build the error returned by a strict codec when it receives an
387404/// inline Python-UDF payload it has been told not to deserialize.
388405fn refuse_inline_payload ( kind : & str , name : & str ) -> datafusion:: error:: DataFusionError {
@@ -429,7 +446,10 @@ impl PythonPhysicalCodec {
429446 & self . inner
430447 }
431448
432- /// See [`PythonLogicalCodec::with_python_udf_inlining`].
449+ /// Toggle inline encoding of Python UDFs on this physical codec.
450+ ///
451+ /// Mirrors [`PythonLogicalCodec::with_python_udf_inlining`]; see
452+ /// that method for the full security and portability discussion.
433453 pub fn with_python_udf_inlining ( mut self , enabled : bool ) -> Self {
434454 self . python_udf_inlining = enabled;
435455 self
@@ -472,8 +492,8 @@ impl PhysicalExtensionCodec for PythonPhysicalCodec {
472492 if let Some ( udf) = try_decode_python_scalar_udf ( buf) ? {
473493 return Ok ( udf) ;
474494 }
475- } else if buf . starts_with ( PY_SCALAR_UDF_FAMILY ) {
476- return Err ( refuse_inline_payload ( "scalar UDF" , name) ) ;
495+ } else {
496+ refuse_if_inline ( buf , PY_SCALAR_UDF_FAMILY , "scalar UDF" , name) ? ;
477497 }
478498 self . inner . try_decode_udf ( name, buf)
479499 }
@@ -502,8 +522,8 @@ impl PhysicalExtensionCodec for PythonPhysicalCodec {
502522 if let Some ( udaf) = try_decode_python_udaf ( buf) ? {
503523 return Ok ( udaf) ;
504524 }
505- } else if buf . starts_with ( PY_AGG_UDF_FAMILY ) {
506- return Err ( refuse_inline_payload ( "aggregate UDF" , name) ) ;
525+ } else {
526+ refuse_if_inline ( buf , PY_AGG_UDF_FAMILY , "aggregate UDF" , name) ? ;
507527 }
508528 self . inner . try_decode_udaf ( name, buf)
509529 }
@@ -520,8 +540,8 @@ impl PhysicalExtensionCodec for PythonPhysicalCodec {
520540 if let Some ( udwf) = try_decode_python_udwf ( buf) ? {
521541 return Ok ( udwf) ;
522542 }
523- } else if buf . starts_with ( PY_WINDOW_UDF_FAMILY ) {
524- return Err ( refuse_inline_payload ( "window UDF" , name) ) ;
543+ } else {
544+ refuse_if_inline ( buf , PY_WINDOW_UDF_FAMILY , "window UDF" , name) ? ;
525545 }
526546 self . inner . try_decode_udwf ( name, buf)
527547 }
0 commit comments