Mercurial > octave
comparison libinterp/corefcn/debug.cc @ 33240:4e5bc9c4f657
use std::stoi or std::stoul instead of atoi (bug #65342)
The std::stoi and std::stoul functions allow us to distinguish between
invalid values and out of range values instead of just returning 0 for
any conversion failure as atoi does. In the following changes, we now
attempt to provide better diagnostics where possible.
* pathsearch.cc (directory_path::init): Use std::stoul instead of
atoi. Issue warnings for out of range or invalid values.
* __init_fltk__.cc (fltk_uimenu::add_entry): Use std::stoi instead of atoi.
* event-manager.cc (F__event_manager_file_dialog__): Use std::stoi
instead of atoi.
* bp-table.cc (bp_table::parse_dbfunction_params): Use std::stoi
instead of atoi.
* data-conv.cc (oct_data_conv::string_to_data_type): Use std::stoi
instead of atoi.
* debug.cc (parse_start_end, parse_integer_argument): New static functions.
(Fdbtype): Use parse_start_end to improve parsing of integer arguments.
(Fdblist, Fdbstack, do_dbupdown): Use parse_integer_argument to
improve handling of integer argument values.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 23 Mar 2024 12:13:17 -0400 |
parents | 51fdc7b36abd |
children | 69eb4c27d8c8 |
comparison
equal
deleted
inserted
replaced
33239:775dde0cb3e5 | 33240:4e5bc9c4f657 |
---|---|
590 tw.debug_where (octave_stdout); | 590 tw.debug_where (octave_stdout); |
591 | 591 |
592 return ovl (); | 592 return ovl (); |
593 } | 593 } |
594 | 594 |
595 static bool | |
596 parse_start_end (const std::string& arg, int& start, int& end, const char *who) | |
597 { | |
598 start = 0; | |
599 end = 0; | |
600 | |
601 std::size_t ind = arg.find (':'); | |
602 | |
603 if (ind != std::string::npos) // (start:end) | |
604 { | |
605 std::string start_str = arg.substr (0, ind); | |
606 std::string end_str = arg.substr (ind+1); | |
607 | |
608 try | |
609 { | |
610 start = std::stoi (start_str); | |
611 | |
612 if (end_str == "end") | |
613 end = std::numeric_limits<int>::max (); | |
614 else | |
615 end = std::stoi (end_str); | |
616 } | |
617 catch (const std::invalid_argument&) | |
618 { | |
619 error ("%s: invalid integer conversion while parsing range '%s'", who, arg.c_str ()); | |
620 } | |
621 catch (const std::out_of_range&) | |
622 { | |
623 error ("%s: integer value out of bounds while parsing range '%s'", who, arg.c_str ()); | |
624 } | |
625 | |
626 if (std::min (start, end) <= 0) | |
627 error ("%s: start and end lines must be >= 1\n", who); | |
628 | |
629 if (start > end) | |
630 error ("%s: start line must be less than end line\n", who); | |
631 } | |
632 else // (dbtype lineno) | |
633 { | |
634 try | |
635 { | |
636 int line = std::stoi (arg); | |
637 | |
638 if (line <= 0) | |
639 error ("%s: start and end lines must be >= 1\n", who); | |
640 | |
641 start = line; | |
642 end = line; | |
643 } | |
644 catch (const std::invalid_argument&) | |
645 { | |
646 // May be a name instead of a number. | |
647 return false; | |
648 } | |
649 catch (const std::out_of_range&) | |
650 { | |
651 error ("%s: integer value out of bounds while parsing '%s'", who, arg.c_str ()); | |
652 } | |
653 } | |
654 | |
655 return true; | |
656 } | |
657 | |
595 DEFMETHOD (dbtype, interp, args, , | 658 DEFMETHOD (dbtype, interp, args, , |
596 doc: /* -*- texinfo -*- | 659 doc: /* -*- texinfo -*- |
597 @deftypefn {} {} dbtype | 660 @deftypefn {} {} dbtype |
598 @deftypefnx {} {} dbtype @var{lineno} | 661 @deftypefnx {} {} dbtype @var{lineno} |
599 @deftypefnx {} {} dbtype @var{startl:endl} | 662 @deftypefnx {} {} dbtype @var{startl:endl} |
631 | 694 |
632 case 1: // (dbtype start:end) || (dbtype fcn) || (dbtype lineno) | 695 case 1: // (dbtype start:end) || (dbtype fcn) || (dbtype lineno) |
633 { | 696 { |
634 std::string arg = argv[1]; | 697 std::string arg = argv[1]; |
635 | 698 |
636 std::size_t ind = arg.find (':'); | 699 if (! parse_start_end (arg, start, end, "dbtype")) |
637 | 700 fcn_name = arg; |
638 if (ind != std::string::npos) // (dbtype start:end) | |
639 { | |
640 std::string start_str = arg.substr (0, ind); | |
641 std::string end_str = arg.substr (ind + 1); | |
642 | |
643 start = atoi (start_str.c_str ()); | |
644 if (end_str == "end") | |
645 end = std::numeric_limits<int>::max (); | |
646 else | |
647 end = atoi (end_str.c_str ()); | |
648 | |
649 if (std::min (start, end) <= 0) | |
650 error ("dbtype: start and end lines must be >= 1\n"); | |
651 | |
652 if (start > end) | |
653 error ("dbtype: start line must be less than end line\n"); | |
654 } | |
655 else // (dbtype fcn) || (dbtype lineno) | |
656 { | |
657 int line = atoi (arg.c_str ()); | |
658 | |
659 if (line == 0) // (dbtype fcn) | |
660 fcn_name = arg; | |
661 else // (dbtype lineno) | |
662 { | |
663 if (line <= 0) | |
664 error ("dbtype: start and end lines must be >= 1\n"); | |
665 | |
666 start = line; | |
667 end = line; | |
668 } | |
669 } | |
670 } | 701 } |
671 break; | 702 break; |
672 | 703 |
673 case 2: // (dbtype fcn start:end) || (dbtype fcn start) | 704 case 2: // (dbtype fcn start:end) || (dbtype fcn start) |
674 { | 705 { |
675 fcn_name = argv[1]; | 706 fcn_name = argv[1]; |
676 | 707 |
677 std::string arg = argv[2]; | 708 if (! parse_start_end (argv[2], start, end, "dbtype")) |
678 std::size_t ind = arg.find (':'); | 709 error ("dbtype: expecting start:end or location argument, found '%s'", argv[2].c_str ()); |
679 | |
680 if (ind != std::string::npos) | |
681 { | |
682 std::string start_str = arg.substr (0, ind); | |
683 std::string end_str = arg.substr (ind + 1); | |
684 | |
685 start = atoi (start_str.c_str ()); | |
686 if (end_str == "end") | |
687 end = std::numeric_limits<int>::max (); | |
688 else | |
689 end = atoi (end_str.c_str ()); | |
690 } | |
691 else | |
692 { | |
693 start = atoi (arg.c_str ()); | |
694 end = start; | |
695 } | |
696 | |
697 if (std::min (start, end) <= 0) | |
698 error ("dbtype: start and end lines must be >= 1\n"); | |
699 | |
700 if (start > end) | |
701 error ("dbtype: start line must be less than end line\n"); | |
702 } | 710 } |
703 break; | 711 break; |
704 | 712 |
705 default: | 713 default: |
706 error ("dbtype: expecting zero, one, or two arguments\n"); | 714 error ("dbtype: expecting zero, one, or two arguments\n"); |
721 | 729 |
722 octave::display_file_lines (octave_stdout, file_name, start, end, -1, "", "dbtype"); | 730 octave::display_file_lines (octave_stdout, file_name, start, end, -1, "", "dbtype"); |
723 } | 731 } |
724 | 732 |
725 return ovl (); | 733 return ovl (); |
734 } | |
735 | |
736 static int | |
737 parse_integer_argument (const std::string& arg, const char *who) | |
738 { | |
739 int n = 0; | |
740 | |
741 try | |
742 { | |
743 n = std::stoi (arg); | |
744 } | |
745 catch (const std::invalid_argument&) | |
746 { | |
747 error ("%s: invalid value of N, found '%s'", arg.c_str (), who); | |
748 } | |
749 catch (const std::out_of_range&) | |
750 { | |
751 error ("%s: value of N ('%s') is out of range", arg.c_str (), who); | |
752 } | |
753 | |
754 return n; | |
726 } | 755 } |
727 | 756 |
728 DEFMETHOD (dblist, interp, args, , | 757 DEFMETHOD (dblist, interp, args, , |
729 doc: /* -*- texinfo -*- | 758 doc: /* -*- texinfo -*- |
730 @deftypefn {} {} dblist | 759 @deftypefn {} {} dblist |
746 if (numel == 1) | 775 if (numel == 1) |
747 { | 776 { |
748 octave_value arg = args(0); | 777 octave_value arg = args(0); |
749 | 778 |
750 if (arg.is_string ()) | 779 if (arg.is_string ()) |
751 { | 780 n = parse_integer_argument (arg.string_value (), "dblist"); |
752 std::string s_arg = arg.string_value (); | |
753 | |
754 n = atoi (s_arg.c_str ()); | |
755 } | |
756 else | 781 else |
757 n = args(0).int_value (); | 782 n = args(0).int_value (); |
758 | 783 |
759 if (n < 0) | 784 if (n < 0) |
760 error ("dblist: N must be a non-negative integer"); | 785 error ("dblist: N must be a non-negative integer"); |
796 | 821 |
797 // Skip "-completenames", octave returns full names anyway. | 822 // Skip "-completenames", octave returns full names anyway. |
798 if (s_arg == "-completenames") | 823 if (s_arg == "-completenames") |
799 continue; | 824 continue; |
800 | 825 |
801 n = atoi (s_arg.c_str ()); | 826 n = parse_integer_argument (s_arg, "dbstack"); |
802 } | 827 } |
803 else | 828 else |
804 n = arg.int_value (); | 829 n = arg.int_value (); |
805 | 830 |
806 if (n < 0) | 831 if (n < 0) |
942 if (args.length () == 1) | 967 if (args.length () == 1) |
943 { | 968 { |
944 octave_value arg = args(0); | 969 octave_value arg = args(0); |
945 | 970 |
946 if (arg.is_string ()) | 971 if (arg.is_string ()) |
947 { | 972 n = parse_integer_argument (arg.string_value (), who.c_str ()); |
948 std::string s_arg = arg.string_value (); | |
949 | |
950 n = atoi (s_arg.c_str ()); | |
951 } | |
952 else | 973 else |
953 n = args(0).int_value (); | 974 n = args(0).int_value (); |
954 } | 975 } |
955 | 976 |
956 if (who == "dbup") | 977 if (who == "dbup") |
1036 n = -1; | 1057 n = -1; |
1037 else if (arg == "out") | 1058 else if (arg == "out") |
1038 n = -2; | 1059 n = -2; |
1039 else | 1060 else |
1040 { | 1061 { |
1041 n = atoi (arg.c_str ()); | 1062 n = parse_integer_argument (arg, "dbstep"); |
1042 | 1063 |
1043 if (n < 1) | 1064 if (n < 1) |
1044 error ("dbstep: invalid argument"); | 1065 error ("dbstep: N must be greater than zero"); |
1045 } | 1066 } |
1046 } | 1067 } |
1047 else | 1068 else |
1048 n = 1; | 1069 n = 1; |
1049 | 1070 |