63
63
import static com .oracle .graal .python .builtins .objects .cext .hpy .GraalHPyNativeSymbol .GRAAL_HPY_WRITE_UL ;
64
64
65
65
import java .io .PrintWriter ;
66
+ import java .nio .ByteBuffer ;
67
+ import java .nio .charset .CharacterCodingException ;
66
68
import java .nio .charset .Charset ;
69
+ import java .nio .charset .CodingErrorAction ;
67
70
import java .nio .charset .StandardCharsets ;
68
71
import java .util .logging .Level ;
69
72
230
233
import com .oracle .truffle .api .object .DynamicObjectLibrary ;
231
234
import com .oracle .truffle .api .profiles .ConditionProfile ;
232
235
import com .oracle .truffle .api .profiles .ValueProfile ;
233
- import java .nio .ByteBuffer ;
234
- import java .nio .charset .CharacterCodingException ;
235
- import java .nio .charset .CodingErrorAction ;
236
236
237
237
@ SuppressWarnings ("static-method" )
238
238
public abstract class GraalHPyContextFunctions {
@@ -3418,13 +3418,18 @@ Object execute(Object[] arguments,
3418
3418
@ Cached HPyAsContextNode asContextNode ,
3419
3419
@ Cached FromCharPointerNode fromCharPointerNode ,
3420
3420
@ Cached HPyAsHandleNode asHandleNode ,
3421
+ @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ,
3421
3422
@ Cached CastToJavaStringNode castStr ,
3423
+ @ Cached HPyRaiseNode raiseNode ,
3422
3424
@ Cached GilNode gil ) throws ArityException {
3423
3425
checkArity (arguments , 4 );
3424
3426
boolean mustRelease = gil .acquire ();
3425
3427
try {
3426
3428
GraalHPyContext context = asContextNode .execute (arguments [0 ]);
3427
3429
PyCapsule result = new PyCapsule ();
3430
+ if (interopLib .isNull (arguments [1 ])) {
3431
+ return raiseNode .raiseWithoutFrame (context , GraalHPyHandle .NULL_HANDLE , ValueError , "HPyCapsule_New called with null pointer" );
3432
+ }
3428
3433
result .setPointer (arguments [1 ]);
3429
3434
try {
3430
3435
if (!nameLib .isPointer (arguments [2 ]) || nameLib .asPointer (arguments [2 ]) != 0 ) {
@@ -3443,6 +3448,7 @@ Object execute(Object[] arguments,
3443
3448
3444
3449
@ ExportLibrary (InteropLibrary .class )
3445
3450
public static final class GraalHPyCapsuleGet extends GraalHPyContextFunction {
3451
+ static final String SUFFIX = " called with invalid PyCapsule object" ;
3446
3452
3447
3453
@ TruffleBoundary
3448
3454
private static byte [] getBytes (PyCapsule pyCapsule ) {
@@ -3453,27 +3459,28 @@ private static byte[] getBytes(PyCapsule pyCapsule) {
3453
3459
Object execute (Object [] arguments ,
3454
3460
@ Cached HPyAsContextNode asContextNode ,
3455
3461
@ Cached HPyAsPythonObjectNode asCapsule ,
3462
+ @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ,
3456
3463
@ Cached FromCharPointerNode fromCharPointerNode ,
3457
3464
@ Cached CastToJavaStringNode castStr ,
3458
3465
@ Cached CastToJavaIntExactNode castInt ,
3466
+ @ Cached PRaiseNode raiseNode ,
3467
+ @ Cached HPyTransformExceptionToNativeNode transformExceptionToNativeNode ,
3459
3468
@ Cached GilNode gil ) throws ArityException {
3460
3469
checkArity (arguments , 4 );
3461
3470
boolean mustRelease = gil .acquire ();
3471
+ GraalHPyContext context = null ;
3462
3472
try {
3463
- GraalHPyContext context = asContextNode .execute (arguments [0 ]);
3473
+ context = asContextNode .execute (arguments [0 ]);
3464
3474
Object capsule = asCapsule .execute (context , arguments [1 ]);
3465
- if (!(capsule instanceof PyCapsule )) {
3466
- throw CompilerDirectives .shouldNotReachHere ("TODO: raise ValueError" );
3467
- }
3468
- PyCapsule pyCapsule = (PyCapsule ) capsule ;
3469
- String name = castStr .execute (fromCharPointerNode .execute (arguments [3 ]));
3470
- if (!pyCapsule .getName ().equals (name )) {
3471
- throw CompilerDirectives .shouldNotReachHere ("TODO: raise ValueError" );
3472
- }
3473
3475
int key = castInt .execute (arguments [2 ]);
3476
+ isLegalCapsule (capsule , key , raiseNode );
3477
+ PyCapsule pyCapsule = (PyCapsule ) capsule ;
3474
3478
Object result ;
3475
3479
switch (key ) {
3476
3480
case CapsuleKey .Pointer :
3481
+ if (!nameMatches (pyCapsule , arguments [3 ], interopLib , fromCharPointerNode , castStr )) {
3482
+ throw raiseNode .raise (ValueError , "HPyCapsule_GetPointer called with incorrect name" );
3483
+ }
3477
3484
result = pyCapsule .getPointer ();
3478
3485
break ;
3479
3486
case CapsuleKey .Context :
@@ -3486,13 +3493,55 @@ Object execute(Object[] arguments,
3486
3493
result = pyCapsule .getDestructor ();
3487
3494
break ;
3488
3495
default :
3489
- throw CompilerDirectives .shouldNotReachHere ("TODO: raise ValueError" );
3496
+ throw CompilerDirectives .shouldNotReachHere ("invalid key" );
3497
+ }
3498
+ // never allow Java 'null' to be returned
3499
+ if (result == null ) {
3500
+ return context .getContext ().getNativeNull ().getPtr ();
3490
3501
}
3491
3502
return result ;
3503
+ } catch (PException e ) {
3504
+ transformExceptionToNativeNode .execute (context , e );
3505
+ return GraalHPyHandle .NULL_HANDLE ;
3492
3506
} finally {
3493
3507
gil .release (mustRelease );
3494
3508
}
3495
3509
}
3510
+
3511
+ private static boolean nameMatches (PyCapsule capsule , Object namePtr , InteropLibrary interopLib , FromCharPointerNode fromCharPointerNode , CastToJavaStringNode castStr ) {
3512
+ boolean isCapsuleNameNull = capsule .getName () == null ;
3513
+ boolean isNamePtrNull = interopLib .isNull (namePtr );
3514
+
3515
+ // if one of them is NULL, then both need to be NULL
3516
+ if (isCapsuleNameNull || isNamePtrNull ) {
3517
+ return isCapsuleNameNull && isNamePtrNull ;
3518
+ }
3519
+
3520
+ String name = castStr .execute (fromCharPointerNode .execute (namePtr ));
3521
+ return capsule .getName ().equals (name );
3522
+ }
3523
+
3524
+ private static void isLegalCapsule (Object object , int key , PRaiseNode raiseNode ) {
3525
+ if (!(object instanceof PyCapsule ) || ((PyCapsule ) object ).getPointer () == null ) {
3526
+ throw raiseNode .raise (ValueError , getErrorMessage (key ));
3527
+ }
3528
+ }
3529
+
3530
+ @ TruffleBoundary
3531
+ private static String getErrorMessage (int key ) {
3532
+ switch (key ) {
3533
+ case CapsuleKey .Pointer :
3534
+ return "HPyCapsule_GetPointer" + SUFFIX ;
3535
+ case CapsuleKey .Context :
3536
+ return "HPyCapsule_GetContext" + SUFFIX ;
3537
+ case CapsuleKey .Name :
3538
+ return "HPyCapsule_GetName" + SUFFIX ;
3539
+ case CapsuleKey .Destructor :
3540
+ return "HPyCapsule_GetDestructor" + SUFFIX ;
3541
+ default :
3542
+ throw CompilerDirectives .shouldNotReachHere ("invalid key" );
3543
+ }
3544
+ }
3496
3545
}
3497
3546
3498
3547
@ ExportLibrary (InteropLibrary .class )
@@ -3504,19 +3553,24 @@ Object execute(Object[] arguments,
3504
3553
@ Cached FromCharPointerNode fromCharPointerNode ,
3505
3554
@ Cached CastToJavaStringNode castStr ,
3506
3555
@ Cached CastToJavaIntExactNode castInt ,
3556
+ @ Cached PRaiseNode raiseNode ,
3557
+ @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ,
3558
+ @ Cached HPyTransformExceptionToNativeNode transformExceptionToNativeNode ,
3507
3559
@ Cached GilNode gil ) throws ArityException {
3508
3560
checkArity (arguments , 4 );
3509
3561
boolean mustRelease = gil .acquire ();
3562
+ GraalHPyContext context = null ;
3510
3563
try {
3511
- GraalHPyContext context = asContextNode .execute (arguments [0 ]);
3564
+ context = asContextNode .execute (arguments [0 ]);
3512
3565
Object capsule = asCapsule .execute (context , arguments [1 ]);
3513
- if (!(capsule instanceof PyCapsule )) {
3514
- throw CompilerDirectives .shouldNotReachHere ("TODO: raise ValueError" );
3515
- }
3516
- PyCapsule pyCapsule = (PyCapsule ) capsule ;
3517
3566
int key = castInt .execute (arguments [2 ]);
3567
+ isLegalCapsule (capsule , key , raiseNode );
3568
+ PyCapsule pyCapsule = (PyCapsule ) capsule ;
3518
3569
switch (key ) {
3519
3570
case CapsuleKey .Pointer :
3571
+ if (interopLib .isNull (arguments [3 ])) {
3572
+ throw raiseNode .raise (ValueError , "PyCapsule_SetPointer called with null pointer" );
3573
+ }
3520
3574
pyCapsule .setPointer (arguments [3 ]);
3521
3575
break ;
3522
3576
case CapsuleKey .Context :
@@ -3529,13 +3583,38 @@ Object execute(Object[] arguments,
3529
3583
pyCapsule .setDestructor (arguments [3 ]);
3530
3584
break ;
3531
3585
default :
3532
- throw CompilerDirectives .shouldNotReachHere ("TODO: raise ValueError " );
3586
+ throw CompilerDirectives .shouldNotReachHere ("invalid key " );
3533
3587
}
3534
3588
return 0 ;
3589
+ } catch (PException e ) {
3590
+ transformExceptionToNativeNode .execute (context , e );
3591
+ return -1 ;
3535
3592
} finally {
3536
3593
gil .release (mustRelease );
3537
3594
}
3538
3595
}
3596
+
3597
+ private static void isLegalCapsule (Object object , int key , PRaiseNode raiseNode ) {
3598
+ if (!(object instanceof PyCapsule ) || ((PyCapsule ) object ).getPointer () == null ) {
3599
+ throw raiseNode .raise (ValueError , getErrorMessage (key ));
3600
+ }
3601
+ }
3602
+
3603
+ @ TruffleBoundary
3604
+ private static String getErrorMessage (int key ) {
3605
+ switch (key ) {
3606
+ case CapsuleKey .Pointer :
3607
+ return "HPyCapsule_GetPointer" + GraalHPyCapsuleGet .SUFFIX ;
3608
+ case CapsuleKey .Context :
3609
+ return "HPyCapsule_GetContext" + GraalHPyCapsuleGet .SUFFIX ;
3610
+ case CapsuleKey .Name :
3611
+ return "HPyCapsule_GetName" + GraalHPyCapsuleGet .SUFFIX ;
3612
+ case CapsuleKey .Destructor :
3613
+ return "HPyCapsule_GetDestructor" + GraalHPyCapsuleGet .SUFFIX ;
3614
+ default :
3615
+ throw CompilerDirectives .shouldNotReachHere ("invalid key" );
3616
+ }
3617
+ }
3539
3618
}
3540
3619
3541
3620
@ ExportLibrary (InteropLibrary .class )
@@ -3544,6 +3623,7 @@ public static final class GraalHPyCapsuleIsValid extends GraalHPyContextFunction
3544
3623
Object execute (Object [] arguments ,
3545
3624
@ Cached HPyAsContextNode asContextNode ,
3546
3625
@ Cached HPyAsPythonObjectNode asCapsule ,
3626
+ @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ,
3547
3627
@ Cached FromCharPointerNode fromCharPointerNode ,
3548
3628
@ Cached CastToJavaStringNode castStr ,
3549
3629
@ Cached GilNode gil ) throws ArityException {
@@ -3556,8 +3636,7 @@ Object execute(Object[] arguments,
3556
3636
return 0 ;
3557
3637
}
3558
3638
PyCapsule pyCapsule = (PyCapsule ) capsule ;
3559
- String name = castStr .execute (fromCharPointerNode .execute (arguments [3 ]));
3560
- if (!pyCapsule .getName ().equals (name )) {
3639
+ if (!GraalHPyCapsuleGet .nameMatches (pyCapsule , arguments [2 ], interopLib , fromCharPointerNode , castStr )) {
3561
3640
return 0 ;
3562
3641
}
3563
3642
return 1 ;
0 commit comments