Browse code

core: reworked string-number conversion to catch out of limits values

Daniel-Constantin Mierla authored on 01/12/2021 08:34:28
Showing 1 changed files
... ...
@@ -627,37 +627,43 @@ static inline void strlower(str* _s)
627 627
 	}
628 628
 }
629 629
 
630
-
631
-#define str2unval(_s, _r, _vmax) do { \
632
-		int i; \
633
-		if (_r == NULL) return -1; \
630
+#define str2unval(_s, _r, _vtype, _vmax) do { \
631
+		_vtype limitmul; \
632
+		int i, c, limitrst; \
633
+		if((_s == NULL) || (_r == NULL) || (_s->len < 0) || (_s->s == NULL)) { \
634
+			return -1; \
635
+		} \
634 636
 		*_r = 0; \
635
-		if (_s == NULL) return -1; \
636
-		if (_s->len < 0) return -1; \
637
-		if (_s->s == NULL) return -1; \
638
-		for(i = 0; i < _s->len; i++) { \
639
-			if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) { \
640
-				if(*_r > _vmax/10) { \
641
-					return -1; \
642
-				} \
643
-				*_r *= 10; \
644
-				if(*_r > _vmax - (_s->s[i] - '0')) { \
645
-					return -1; \
646
-				} \
647
-				*_r += _s->s[i] - '0'; \
648
-			} else { \
637
+		i = 0; \
638
+		if (_s->s[0] == '+') { \
639
+			i++; \
640
+		} \
641
+		limitmul = _vmax / 10; \
642
+		limitrst = _vmax % 10; \
643
+		for(; i < _s->len; i++) { \
644
+			c = (unsigned char)_s->s[i]; \
645
+			if (c < '0' || c > '9') { \
646
+				return -1; \
647
+			} \
648
+			c -= '0'; \
649
+			if (*_r > limitmul || (*_r == limitmul && c > limitrst)) { \
650
+				*_r = _vmax; \
649 651
 				return -1; \
652
+			} else { \
653
+				*_r *= 10; \
654
+				*_r += c; \
650 655
 			} \
651 656
 		} \
652 657
 		return 0; \
653 658
 	} while(0)
654 659
 
660
+
655 661
 /*
656 662
  * Convert an str to unsigned long
657 663
  */
658 664
 static inline int str2ulong(str* _s, unsigned long* _r)
659 665
 {
660
-	str2unval(_s, _r, ULONG_MAX);
666
+	str2unval(_s, _r, long, ULONG_MAX);
661 667
 }
662 668
 
663 669
 /*
... ...
@@ -665,56 +671,69 @@ static inline int str2ulong(str* _s, unsigned long* _r)
665 671
  */
666 672
 static inline int str2int(str* _s, unsigned int* _r)
667 673
 {
668
-	str2unval(_s, _r, UINT_MAX);
674
+	str2unval(_s, _r, int, UINT_MAX);
669 675
 }
670 676
 
671
-#define str2snval(_s, _r, _vmin, _vmax) do { \
672
-		int i; \
673
-		int sign; \
674
-		long long ll; \
675
-		if (_s == NULL) return -1; \
676
-		if (_r == NULL) return -1; \
677
-		if (_s->len < 0) return -1; \
678
-		if (_s->s == NULL) return -1; \
677
+
678
+#define str2snval(_s, _r, _vtype, _vmin, _vmax) do { \
679
+		_vtype limitmul; \
680
+		int i, c, neg, limitrst; \
681
+		if((_s == NULL) || (_r == NULL) || (_s->len < 0) || (_s->s == NULL)) { \
682
+			return -1; \
683
+		} \
679 684
 		*_r = 0; \
680
-		sign = 1; \
685
+		neg = 0; \
681 686
 		i = 0; \
682 687
 		if (_s->s[0] == '+') { \
683 688
 			i++; \
684 689
 		} else if (_s->s[0] == '-') { \
685
-			sign = -1; \
690
+			neg = 1; \
686 691
 			i++; \
687 692
 		} \
693
+		limitmul = neg ? _vmin : _vmax; \
694
+		limitrst = limitmul % 10; \
695
+		limitmul /= 10; \
696
+		if (neg) { \
697
+			if (limitrst > 0) { \
698
+				limitrst -= 10; \
699
+				limitmul += 1; \
700
+			} \
701
+			limitrst = -limitrst; \
702
+		} \
688 703
 		for(; i < _s->len; i++) { \
689
-			if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) { \
690
-				if(*_r > _vmax/10) { \
704
+			c = (unsigned char)_s->s[i]; \
705
+			if (c < '0' || c > '9') { \
706
+				return -1; \
707
+			} \
708
+			c -= '0'; \
709
+			if (neg) { \
710
+				if (*_r < limitmul || (*_r == limitmul && c > limitrst)) { \
711
+					*_r = _vmin; \
691 712
 					return -1; \
713
+				} else { \
714
+					*_r *= 10; \
715
+					*_r -= c; \
692 716
 				} \
693
-				*_r *= 10; \
694
-				if(*_r > _vmax - (_s->s[i] - '0')) { \
717
+			} else { \
718
+				if (*_r > limitmul || (*_r == limitmul && c > limitrst)) { \
719
+					*_r = _vmax; \
695 720
 					return -1; \
721
+				} else { \
722
+					*_r *= 10; \
723
+					*_r += c; \
696 724
 				} \
697
-				*_r += _s->s[i] - '0'; \
698
-			} else { \
699
-				return -1; \
700 725
 			} \
701 726
 		} \
702
-		if(sign < 0) { \
703
-			ll = (long long)(*_r) * sign; \
704
-			if(ll < _vmin) { \
705
-				return -1; \
706
-			} \
707
-			*_r *= sign; \
708
-		} \
709 727
 		return 0; \
710 728
 	} while(0)
711 729
 
730
+
712 731
 /*
713 732
  * Convert an str to signed long
714 733
  */
715 734
 static inline int str2slong(str* _s, long* _r)
716 735
 {
717
-	str2snval(_s, _r, LONG_MIN, LONG_MAX);
736
+	str2snval(_s, _r, long, LONG_MIN, LONG_MAX);
718 737
 }
719 738
 
720 739
 
... ...
@@ -723,7 +742,7 @@ static inline int str2slong(str* _s, long* _r)
723 742
  */
724 743
 static inline int str2sint(str* _s, int* _r)
725 744
 {
726
-	str2snval(_s, _r, INT_MIN, INT_MAX);
745
+	str2snval(_s, _r, int, INT_MIN, INT_MAX);
727 746
 }
728 747
 
729 748