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