@@ -3359,38 +3359,75 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
3359
3359
PERL_ARGS_ASSERT_DO_SHMIO ;
3360
3360
PERL_UNUSED_ARG (sp );
3361
3361
3362
- char * shm ;
3363
- struct shmid_ds shmds ;
3364
- const I32 id = SvIVx (* ++ mark );
3365
- SV * const mstr = * ++ mark ;
3366
- const I32 mpos = SvIVx (* ++ mark );
3367
- const I32 msize = SvIVx (* ++ mark );
3362
+ const IV iv_id = SvIVx (* ++ mark );
3363
+ SV * const mstr = * ++ mark ;
3364
+ const IV iv_mpos = SvIVx (* ++ mark );
3365
+ const IV iv_msize = SvIVx (* ++ mark );
3366
+
3367
+ /* must fit in int */
3368
+ if (
3369
+ iv_id < 0
3370
+ || (sizeof (IV ) > sizeof (int ) && iv_id > PERL_INT_MAX )
3371
+ ) {
3372
+ SETERRNO (EINVAL ,LIB_INVARG );
3373
+ return -1 ;
3374
+ }
3375
+ const int id = iv_id ;
3368
3376
3369
- SETERRNO (0 ,0 );
3370
- if (shmctl (id , IPC_STAT , & shmds ) == -1 )
3377
+ /* must fit in both size_t and STRLEN (a.k.a Size_t) */
3378
+ if (
3379
+ iv_mpos < 0
3380
+ || (sizeof (IV ) > sizeof (size_t ) && iv_mpos > (IV )SIZE_MAX )
3381
+ || (sizeof (IV ) > sizeof (STRLEN ) && iv_mpos > (IV )(STRLEN )- 1 )
3382
+ ) {
3383
+ SETERRNO (EFAULT ,SS_ACCVIO );
3371
3384
return -1 ;
3372
- if (mpos < 0 || msize < 0
3373
- || (size_t )mpos + msize > (size_t )shmds .shm_segsz ) {
3374
- SETERRNO (EFAULT ,SS_ACCVIO ); /* can't do as caller requested */
3385
+ }
3386
+ const size_t mpos = iv_mpos ;
3387
+
3388
+ /* must fit in both size_t and STRLEN (a.k.a Size_t) */
3389
+ if (
3390
+ iv_msize < 0
3391
+ || (sizeof (IV ) > sizeof (size_t ) && iv_msize > (IV )SIZE_MAX )
3392
+ || (sizeof (IV ) > sizeof (STRLEN ) && iv_msize > (IV )(STRLEN )- 1 )
3393
+ /* for shmread(), we need one extra byte for the NUL terminator */
3394
+ || (optype == OP_SHMREAD && (STRLEN )iv_msize > (STRLEN )- 1 - 1 )
3395
+ ) {
3396
+ SETERRNO (EFAULT ,SS_ACCVIO );
3375
3397
return -1 ;
3376
3398
}
3377
- if (id >= 0 ) {
3378
- shm = (char * )shmat (id , NULL , (optype == OP_SHMREAD ) ? SHM_RDONLY : 0 );
3379
- } else {
3380
- SETERRNO (EINVAL ,LIB_INVARG );
3399
+ const size_t msize = iv_msize ;
3400
+
3401
+ if (SIZE_MAX - mpos < msize ) {
3402
+ /* overflow */
3403
+ SETERRNO (EFAULT ,SS_ACCVIO );
3381
3404
return -1 ;
3382
3405
}
3383
- if (shm == (char * )-1 ) /* I hate System V IPC, I really do */
3406
+ const size_t mpos_end = mpos + msize ;
3407
+
3408
+ SETERRNO (0 ,0 );
3409
+
3410
+ struct shmid_ds shmds ;
3411
+ if (shmctl (id , IPC_STAT , & shmds ) == -1 )
3384
3412
return -1 ;
3413
+
3414
+ if (mpos_end > (size_t )shmds .shm_segsz ) {
3415
+ SETERRNO (EFAULT ,SS_ACCVIO );
3416
+ return -1 ;
3417
+ }
3418
+
3419
+ char * const shm = (char * )shmat (id , NULL , (optype == OP_SHMREAD ) ? SHM_RDONLY : 0 );
3420
+ if (shm == (char * )-1 ) /* I hate System V IPC, I really do */
3421
+ return -1 ;
3422
+
3385
3423
if (optype == OP_SHMREAD ) {
3386
- char * mbuf ;
3387
- /* suppress warning when reading into undef var (tchrist 3/Mar/00) */
3388
3424
SvGETMAGIC (mstr );
3389
3425
SvUPGRADE (mstr , SVt_PV );
3426
+ /* suppress warning when reading into undef var (tchrist 3/Mar/00) */
3390
3427
if (! SvOK (mstr ))
3391
3428
SvPVCLEAR (mstr );
3392
3429
SvPOK_only (mstr );
3393
- mbuf = SvGROW (mstr , (STRLEN )msize + 1 );
3430
+ char * const mbuf = SvGROW (mstr , (STRLEN )msize + 1 );
3394
3431
3395
3432
Copy (shm + mpos , mbuf , msize , char );
3396
3433
SvCUR_set (mstr , msize );
@@ -3400,18 +3437,19 @@ Perl_do_shmio(pTHX_ I32 optype, SV **mark, SV **sp)
3400
3437
SvTAINTED_on (mstr );
3401
3438
}
3402
3439
else {
3403
- STRLEN len ;
3440
+ assert ( optype == OP_SHMWRITE ) ;
3404
3441
3405
- const char * mbuf = SvPVbyte (mstr , len );
3406
- const I32 n = ((I32 )len > msize ) ? msize : (I32 )len ;
3442
+ STRLEN len ;
3443
+ const char * const mbuf = SvPVbyte (mstr , len );
3444
+ const STRLEN n = (len > msize ) ? msize : len ;
3407
3445
Copy (mbuf , shm + mpos , n , char );
3408
3446
if (n < msize )
3409
3447
memzero (shm + mpos + n , msize - n );
3410
3448
}
3411
3449
return shmdt (shm );
3412
3450
#else
3413
3451
/* diag_listed_as: shm%s not implemented */
3414
- Perl_croak ( aTHX_ "shm I/O not implemented" );
3452
+ Perl_croak_nocontext ( "shm I/O not implemented" );
3415
3453
return -1 ;
3416
3454
#endif
3417
3455
}
0 commit comments