@@ -412,8 +412,14 @@ PHP_FUNCTION(dns_check_record)
412
412
413
413
#if HAVE_FULL_DNS_FUNCS
414
414
415
+ #define CHECKCP (n ) do { \
416
+ if (cp + n > end) { \
417
+ return NULL; \
418
+ } \
419
+ } while (0)
420
+
415
421
/* {{{ php_parserr */
416
- static u_char * php_parserr (u_char * cp , querybuf * answer , int type_to_fetch , int store , int raw , zval * * subarray )
422
+ static u_char * php_parserr (u_char * cp , u_char * end , querybuf * answer , int type_to_fetch , int store , int raw , zval * * subarray )
417
423
{
418
424
u_short type , class , dlen ;
419
425
u_long ttl ;
@@ -425,16 +431,18 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
425
431
426
432
* subarray = NULL ;
427
433
428
- n = dn_expand (answer -> qb2 , answer -> qb2 + 65536 , cp , name , sizeof (name ) - 2 );
434
+ n = dn_expand (answer -> qb2 , end , cp , name , sizeof (name ) - 2 );
429
435
if (n < 0 ) {
430
436
return NULL ;
431
437
}
432
438
cp += n ;
433
439
440
+ CHECKCP (10 );
434
441
GETSHORT (type , cp );
435
442
GETSHORT (class , cp );
436
443
GETLONG (ttl , cp );
437
444
GETSHORT (dlen , cp );
445
+ CHECKCP (dlen );
438
446
if (type_to_fetch != T_ANY && type != type_to_fetch ) {
439
447
cp += dlen ;
440
448
return cp ;
@@ -461,12 +469,14 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
461
469
462
470
switch (type ) {
463
471
case DNS_T_A :
472
+ CHECKCP (4 );
464
473
add_assoc_string (* subarray , "type" , "A" , 1 );
465
474
snprintf (name , sizeof (name ), "%d.%d.%d.%d" , cp [0 ], cp [1 ], cp [2 ], cp [3 ]);
466
475
add_assoc_string (* subarray , "ip" , name , 1 );
467
476
cp += dlen ;
468
477
break ;
469
478
case DNS_T_MX :
479
+ CHECKCP (2 );
470
480
add_assoc_string (* subarray , "type" , "MX" , 1 );
471
481
GETSHORT (n , cp );
472
482
add_assoc_long (* subarray , "pri" , n );
@@ -485,7 +495,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
485
495
if (type == DNS_T_PTR ) {
486
496
add_assoc_string (* subarray , "type" , "PTR" , 1 );
487
497
}
488
- n = dn_expand (answer -> qb2 , answer -> qb2 + 65536 , cp , name , (sizeof name ) - 2 );
498
+ n = dn_expand (answer -> qb2 , end , cp , name , (sizeof name ) - 2 );
489
499
if (n < 0 ) {
490
500
return NULL ;
491
501
}
@@ -495,18 +505,22 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
495
505
case DNS_T_HINFO :
496
506
/* See RFC 1010 for values */
497
507
add_assoc_string (* subarray , "type" , "HINFO" , 1 );
508
+ CHECKCP (1 );
498
509
n = * cp & 0xFF ;
499
510
cp ++ ;
511
+ CHECKCP (n );
500
512
add_assoc_stringl (* subarray , "cpu" , (char * )cp , n , 1 );
501
513
cp += n ;
514
+ CHECKCP (1 );
502
515
n = * cp & 0xFF ;
503
516
cp ++ ;
517
+ CHECKCP (n );
504
518
add_assoc_stringl (* subarray , "os" , (char * )cp , n , 1 );
505
519
cp += n ;
506
520
break ;
507
521
case DNS_T_TXT :
508
522
{
509
- int ll = 0 ;
523
+ int l1 = 0 , l2 = 0 ;
510
524
zval * entries = NULL ;
511
525
512
526
add_assoc_string (* subarray , "type" , "TXT" , 1 );
@@ -515,37 +529,41 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
515
529
MAKE_STD_ZVAL (entries );
516
530
array_init (entries );
517
531
518
- while (ll < dlen ) {
519
- n = cp [ll ];
520
- if ((ll + n ) >= dlen ) {
532
+ while (l1 < dlen ) {
533
+ n = cp [l1 ];
534
+ if ((l1 + n ) >= dlen ) {
521
535
// Invalid chunk length, truncate
522
- n = dlen - (ll + 1 );
536
+ n = dlen - (l1 + 1 );
537
+ }
538
+ if (n ) {
539
+ memcpy (tp + l2 , cp + l1 + 1 , n );
540
+ add_next_index_stringl (entries , cp + l1 + 1 , n , 1 );
523
541
}
524
- memcpy (tp + ll , cp + ll + 1 , n );
525
- add_next_index_stringl (entries , cp + ll + 1 , n , 1 );
526
- ll = ll + n + 1 ;
542
+ l1 = l1 + n + 1 ;
543
+ l2 = l2 + n ;
527
544
}
528
- tp [dlen ] = '\0' ;
545
+ tp [l2 ] = '\0' ;
529
546
cp += dlen ;
530
547
531
- add_assoc_stringl (* subarray , "txt" , tp , ( dlen > 0 )? dlen - 1 : 0 , 0 );
548
+ add_assoc_stringl (* subarray , "txt" , tp , l2 , 0 );
532
549
add_assoc_zval (* subarray , "entries" , entries );
533
550
}
534
551
break ;
535
552
case DNS_T_SOA :
536
553
add_assoc_string (* subarray , "type" , "SOA" , 1 );
537
- n = dn_expand (answer -> qb2 , answer -> qb2 + 65536 , cp , name , (sizeof name ) - 2 );
554
+ n = dn_expand (answer -> qb2 , end , cp , name , (sizeof name ) - 2 );
538
555
if (n < 0 ) {
539
556
return NULL ;
540
557
}
541
558
cp += n ;
542
559
add_assoc_string (* subarray , "mname" , name , 1 );
543
- n = dn_expand (answer -> qb2 , answer -> qb2 + 65536 , cp , name , (sizeof name ) - 2 );
560
+ n = dn_expand (answer -> qb2 , end , cp , name , (sizeof name ) - 2 );
544
561
if (n < 0 ) {
545
562
return NULL ;
546
563
}
547
564
cp += n ;
548
565
add_assoc_string (* subarray , "rname" , name , 1 );
566
+ CHECKCP (5 * 4 );
549
567
GETLONG (n , cp );
550
568
add_assoc_long (* subarray , "serial" , n );
551
569
GETLONG (n , cp );
@@ -559,6 +577,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
559
577
break ;
560
578
case DNS_T_AAAA :
561
579
tp = (u_char * )name ;
580
+ CHECKCP (8 * 2 );
562
581
for (i = 0 ; i < 8 ; i ++ ) {
563
582
GETSHORT (s , cp );
564
583
if (s != 0 ) {
@@ -593,6 +612,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
593
612
case DNS_T_A6 :
594
613
p = cp ;
595
614
add_assoc_string (* subarray , "type" , "A6" , 1 );
615
+ CHECKCP (1 );
596
616
n = ((int )cp [0 ]) & 0xFF ;
597
617
cp ++ ;
598
618
add_assoc_long (* subarray , "masklen" , n );
@@ -628,6 +648,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
628
648
cp ++ ;
629
649
}
630
650
for (i = (n + 8 ) / 16 ; i < 8 ; i ++ ) {
651
+ CHECKCP (2 );
631
652
GETSHORT (s , cp );
632
653
if (s != 0 ) {
633
654
if (tp > (u_char * )name ) {
@@ -657,7 +678,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
657
678
tp [0 ] = '\0' ;
658
679
add_assoc_string (* subarray , "ipv6" , name , 1 );
659
680
if (cp < p + dlen ) {
660
- n = dn_expand (answer -> qb2 , answer -> qb2 + 65536 , cp , name , (sizeof name ) - 2 );
681
+ n = dn_expand (answer -> qb2 , end , cp , name , (sizeof name ) - 2 );
661
682
if (n < 0 ) {
662
683
return NULL ;
663
684
}
@@ -666,36 +687,51 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
666
687
}
667
688
break ;
668
689
case DNS_T_SRV :
690
+ CHECKCP (3 * 2 );
669
691
add_assoc_string (* subarray , "type" , "SRV" , 1 );
670
692
GETSHORT (n , cp );
671
693
add_assoc_long (* subarray , "pri" , n );
672
694
GETSHORT (n , cp );
673
695
add_assoc_long (* subarray , "weight" , n );
674
696
GETSHORT (n , cp );
675
697
add_assoc_long (* subarray , "port" , n );
676
- n = dn_expand (answer -> qb2 , answer -> qb2 + 65536 , cp , name , (sizeof name ) - 2 );
698
+ n = dn_expand (answer -> qb2 , end , cp , name , (sizeof name ) - 2 );
677
699
if (n < 0 ) {
678
700
return NULL ;
679
701
}
680
702
cp += n ;
681
703
add_assoc_string (* subarray , "target" , name , 1 );
682
704
break ;
683
705
case DNS_T_NAPTR :
706
+ CHECKCP (2 * 2 );
684
707
add_assoc_string (* subarray , "type" , "NAPTR" , 1 );
685
708
GETSHORT (n , cp );
686
709
add_assoc_long (* subarray , "order" , n );
687
710
GETSHORT (n , cp );
688
711
add_assoc_long (* subarray , "pref" , n );
712
+
713
+ CHECKCP (1 );
689
714
n = (cp [0 ] & 0xFF );
690
- add_assoc_stringl (* subarray , "flags" , (char * )++ cp , n , 1 );
715
+ cp ++ ;
716
+ CHECKCP (n );
717
+ add_assoc_stringl (* subarray , "flags" , (char * )cp , n , 1 );
691
718
cp += n ;
719
+
720
+ CHECKCP (1 );
692
721
n = (cp [0 ] & 0xFF );
693
- add_assoc_stringl (* subarray , "services" , (char * )++ cp , n , 1 );
722
+ cp ++ ;
723
+ CHECKCP (n );
724
+ add_assoc_stringl (* subarray , "services" , (char * )cp , n , 1 );
694
725
cp += n ;
726
+
727
+ CHECKCP (1 );
695
728
n = (cp [0 ] & 0xFF );
696
- add_assoc_stringl (* subarray , "regex" , (char * )++ cp , n , 1 );
729
+ cp ++ ;
730
+ CHECKCP (n );
731
+ add_assoc_stringl (* subarray , "regex" , (char * )cp , n , 1 );
697
732
cp += n ;
698
- n = dn_expand (answer -> qb2 , answer -> qb2 + 65536 , cp , name , (sizeof name ) - 2 );
733
+
734
+ n = dn_expand (answer -> qb2 , end , cp , name , (sizeof name ) - 2 );
699
735
if (n < 0 ) {
700
736
return NULL ;
701
737
}
@@ -888,7 +924,7 @@ PHP_FUNCTION(dns_get_record)
888
924
while (an -- && cp && cp < end ) {
889
925
zval * retval ;
890
926
891
- cp = php_parserr (cp , & answer , type_to_fetch , store_results , raw , & retval );
927
+ cp = php_parserr (cp , end , & answer , type_to_fetch , store_results , raw , & retval );
892
928
if (retval != NULL && store_results ) {
893
929
add_next_index_zval (return_value , retval );
894
930
}
@@ -901,7 +937,7 @@ PHP_FUNCTION(dns_get_record)
901
937
while (ns -- > 0 && cp && cp < end ) {
902
938
zval * retval = NULL ;
903
939
904
- cp = php_parserr (cp , & answer , DNS_T_ANY , authns != NULL , raw , & retval );
940
+ cp = php_parserr (cp , end , & answer , DNS_T_ANY , authns != NULL , raw , & retval );
905
941
if (retval != NULL ) {
906
942
add_next_index_zval (authns , retval );
907
943
}
@@ -913,7 +949,7 @@ PHP_FUNCTION(dns_get_record)
913
949
while (ar -- > 0 && cp && cp < end ) {
914
950
zval * retval = NULL ;
915
951
916
- cp = php_parserr (cp , & answer , DNS_T_ANY , 1 , raw , & retval );
952
+ cp = php_parserr (cp , end , & answer , DNS_T_ANY , 1 , raw , & retval );
917
953
if (retval != NULL ) {
918
954
add_next_index_zval (addtl , retval );
919
955
}
0 commit comments