qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

cutils: add qemu_strtoi & qemu_strtoui parsers for int/unsigned int types

There are qemu_strtoNN functions for various sized integers. This adds two
more for plain int & unsigned int types, with suitable range checking.

Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>

+770
+4
include/qemu/cutils.h
··· 126 126 int qemu_fdatasync(int fd); 127 127 int fcntl_setfl(int fd, int flag); 128 128 int qemu_parse_fd(const char *param); 129 + int qemu_strtoi(const char *nptr, const char **endptr, int base, 130 + int *result); 131 + int qemu_strtoui(const char *nptr, const char **endptr, int base, 132 + unsigned int *result); 129 133 int qemu_strtol(const char *nptr, const char **endptr, int base, 130 134 long *result); 131 135 int qemu_strtoul(const char *nptr, const char **endptr, int base,
+657
tests/test-cutils.c
··· 223 223 g_assert_cmpint(i, ==, 123); 224 224 } 225 225 226 + static void test_qemu_strtoi_correct(void) 227 + { 228 + const char *str = "12345 foo"; 229 + char f = 'X'; 230 + const char *endptr = &f; 231 + int res = 999; 232 + int err; 233 + 234 + err = qemu_strtoi(str, &endptr, 0, &res); 235 + 236 + g_assert_cmpint(err, ==, 0); 237 + g_assert_cmpint(res, ==, 12345); 238 + g_assert(endptr == str + 5); 239 + } 240 + 241 + static void test_qemu_strtoi_null(void) 242 + { 243 + char f = 'X'; 244 + const char *endptr = &f; 245 + int res = 999; 246 + int err; 247 + 248 + err = qemu_strtoi(NULL, &endptr, 0, &res); 249 + 250 + g_assert_cmpint(err, ==, -EINVAL); 251 + g_assert(endptr == NULL); 252 + } 253 + 254 + static void test_qemu_strtoi_empty(void) 255 + { 256 + const char *str = ""; 257 + char f = 'X'; 258 + const char *endptr = &f; 259 + int res = 999; 260 + int err; 261 + 262 + err = qemu_strtoi(str, &endptr, 0, &res); 263 + 264 + g_assert_cmpint(err, ==, -EINVAL); 265 + g_assert(endptr == str); 266 + } 267 + 268 + static void test_qemu_strtoi_whitespace(void) 269 + { 270 + const char *str = " \t "; 271 + char f = 'X'; 272 + const char *endptr = &f; 273 + int res = 999; 274 + int err; 275 + 276 + err = qemu_strtoi(str, &endptr, 0, &res); 277 + 278 + g_assert_cmpint(err, ==, -EINVAL); 279 + g_assert(endptr == str); 280 + } 281 + 282 + static void test_qemu_strtoi_invalid(void) 283 + { 284 + const char *str = " xxxx \t abc"; 285 + char f = 'X'; 286 + const char *endptr = &f; 287 + int res = 999; 288 + int err; 289 + 290 + err = qemu_strtoi(str, &endptr, 0, &res); 291 + 292 + g_assert_cmpint(err, ==, -EINVAL); 293 + g_assert(endptr == str); 294 + } 295 + 296 + static void test_qemu_strtoi_trailing(void) 297 + { 298 + const char *str = "123xxx"; 299 + char f = 'X'; 300 + const char *endptr = &f; 301 + int res = 999; 302 + int err; 303 + 304 + err = qemu_strtoi(str, &endptr, 0, &res); 305 + 306 + g_assert_cmpint(err, ==, 0); 307 + g_assert_cmpint(res, ==, 123); 308 + g_assert(endptr == str + 3); 309 + } 310 + 311 + static void test_qemu_strtoi_octal(void) 312 + { 313 + const char *str = "0123"; 314 + char f = 'X'; 315 + const char *endptr = &f; 316 + int res = 999; 317 + int err; 318 + 319 + err = qemu_strtoi(str, &endptr, 8, &res); 320 + 321 + g_assert_cmpint(err, ==, 0); 322 + g_assert_cmpint(res, ==, 0123); 323 + g_assert(endptr == str + strlen(str)); 324 + 325 + res = 999; 326 + endptr = &f; 327 + err = qemu_strtoi(str, &endptr, 0, &res); 328 + 329 + g_assert_cmpint(err, ==, 0); 330 + g_assert_cmpint(res, ==, 0123); 331 + g_assert(endptr == str + strlen(str)); 332 + } 333 + 334 + static void test_qemu_strtoi_decimal(void) 335 + { 336 + const char *str = "0123"; 337 + char f = 'X'; 338 + const char *endptr = &f; 339 + int res = 999; 340 + int err; 341 + 342 + err = qemu_strtoi(str, &endptr, 10, &res); 343 + 344 + g_assert_cmpint(err, ==, 0); 345 + g_assert_cmpint(res, ==, 123); 346 + g_assert(endptr == str + strlen(str)); 347 + 348 + str = "123"; 349 + res = 999; 350 + endptr = &f; 351 + err = qemu_strtoi(str, &endptr, 0, &res); 352 + 353 + g_assert_cmpint(err, ==, 0); 354 + g_assert_cmpint(res, ==, 123); 355 + g_assert(endptr == str + strlen(str)); 356 + } 357 + 358 + static void test_qemu_strtoi_hex(void) 359 + { 360 + const char *str = "0123"; 361 + char f = 'X'; 362 + const char *endptr = &f; 363 + int res = 999; 364 + int err; 365 + 366 + err = qemu_strtoi(str, &endptr, 16, &res); 367 + 368 + g_assert_cmpint(err, ==, 0); 369 + g_assert_cmpint(res, ==, 0x123); 370 + g_assert(endptr == str + strlen(str)); 371 + 372 + str = "0x123"; 373 + res = 999; 374 + endptr = &f; 375 + err = qemu_strtoi(str, &endptr, 0, &res); 376 + 377 + g_assert_cmpint(err, ==, 0); 378 + g_assert_cmpint(res, ==, 0x123); 379 + g_assert(endptr == str + strlen(str)); 380 + } 381 + 382 + static void test_qemu_strtoi_max(void) 383 + { 384 + char *str = g_strdup_printf("%d", INT_MAX); 385 + char f = 'X'; 386 + const char *endptr = &f; 387 + int res = 999; 388 + int err; 389 + 390 + err = qemu_strtoi(str, &endptr, 0, &res); 391 + 392 + g_assert_cmpint(err, ==, 0); 393 + g_assert_cmpint(res, ==, INT_MAX); 394 + g_assert(endptr == str + strlen(str)); 395 + g_free(str); 396 + } 397 + 398 + static void test_qemu_strtoi_overflow(void) 399 + { 400 + char *str = g_strdup_printf("%lld", (long long)INT_MAX + 1ll); 401 + char f = 'X'; 402 + const char *endptr = &f; 403 + int res = 999; 404 + int err; 405 + 406 + err = qemu_strtoi(str, &endptr, 0, &res); 407 + 408 + g_assert_cmpint(err, ==, -ERANGE); 409 + g_assert_cmpint(res, ==, INT_MAX); 410 + g_assert(endptr == str + strlen(str)); 411 + g_free(str); 412 + } 413 + 414 + static void test_qemu_strtoi_underflow(void) 415 + { 416 + char *str = g_strdup_printf("%lld", (long long)INT_MIN - 1ll); 417 + char f = 'X'; 418 + const char *endptr = &f; 419 + int res = 999; 420 + int err; 421 + 422 + err = qemu_strtoi(str, &endptr, 0, &res); 423 + 424 + g_assert_cmpint(err, ==, -ERANGE); 425 + g_assert_cmpint(res, ==, INT_MIN); 426 + g_assert(endptr == str + strlen(str)); 427 + g_free(str); 428 + } 429 + 430 + static void test_qemu_strtoi_negative(void) 431 + { 432 + const char *str = " \t -321"; 433 + char f = 'X'; 434 + const char *endptr = &f; 435 + int res = 999; 436 + int err; 437 + 438 + err = qemu_strtoi(str, &endptr, 0, &res); 439 + 440 + g_assert_cmpint(err, ==, 0); 441 + g_assert_cmpint(res, ==, -321); 442 + g_assert(endptr == str + strlen(str)); 443 + } 444 + 445 + static void test_qemu_strtoi_full_correct(void) 446 + { 447 + const char *str = "123"; 448 + int res = 999; 449 + int err; 450 + 451 + err = qemu_strtoi(str, NULL, 0, &res); 452 + 453 + g_assert_cmpint(err, ==, 0); 454 + g_assert_cmpint(res, ==, 123); 455 + } 456 + 457 + static void test_qemu_strtoi_full_null(void) 458 + { 459 + char f = 'X'; 460 + const char *endptr = &f; 461 + int res = 999; 462 + int err; 463 + 464 + err = qemu_strtoi(NULL, &endptr, 0, &res); 465 + 466 + g_assert_cmpint(err, ==, -EINVAL); 467 + g_assert(endptr == NULL); 468 + } 469 + 470 + static void test_qemu_strtoi_full_empty(void) 471 + { 472 + const char *str = ""; 473 + int res = 999L; 474 + int err; 475 + 476 + err = qemu_strtoi(str, NULL, 0, &res); 477 + 478 + g_assert_cmpint(err, ==, -EINVAL); 479 + } 480 + 481 + static void test_qemu_strtoi_full_negative(void) 482 + { 483 + const char *str = " \t -321"; 484 + int res = 999; 485 + int err; 486 + 487 + err = qemu_strtoi(str, NULL, 0, &res); 488 + 489 + g_assert_cmpint(err, ==, 0); 490 + g_assert_cmpint(res, ==, -321); 491 + } 492 + 493 + static void test_qemu_strtoi_full_trailing(void) 494 + { 495 + const char *str = "123xxx"; 496 + int res; 497 + int err; 498 + 499 + err = qemu_strtoi(str, NULL, 0, &res); 500 + 501 + g_assert_cmpint(err, ==, -EINVAL); 502 + } 503 + 504 + static void test_qemu_strtoi_full_max(void) 505 + { 506 + char *str = g_strdup_printf("%d", INT_MAX); 507 + int res; 508 + int err; 509 + 510 + err = qemu_strtoi(str, NULL, 0, &res); 511 + 512 + g_assert_cmpint(err, ==, 0); 513 + g_assert_cmpint(res, ==, INT_MAX); 514 + g_free(str); 515 + } 516 + 517 + static void test_qemu_strtoui_correct(void) 518 + { 519 + const char *str = "12345 foo"; 520 + char f = 'X'; 521 + const char *endptr = &f; 522 + unsigned int res = 999; 523 + int err; 524 + 525 + err = qemu_strtoui(str, &endptr, 0, &res); 526 + 527 + g_assert_cmpint(err, ==, 0); 528 + g_assert_cmpuint(res, ==, 12345); 529 + g_assert(endptr == str + 5); 530 + } 531 + 532 + static void test_qemu_strtoui_null(void) 533 + { 534 + char f = 'X'; 535 + const char *endptr = &f; 536 + unsigned int res = 999; 537 + int err; 538 + 539 + err = qemu_strtoui(NULL, &endptr, 0, &res); 540 + 541 + g_assert_cmpint(err, ==, -EINVAL); 542 + g_assert(endptr == NULL); 543 + } 544 + 545 + static void test_qemu_strtoui_empty(void) 546 + { 547 + const char *str = ""; 548 + char f = 'X'; 549 + const char *endptr = &f; 550 + unsigned int res = 999; 551 + int err; 552 + 553 + err = qemu_strtoui(str, &endptr, 0, &res); 554 + 555 + g_assert_cmpint(err, ==, -EINVAL); 556 + g_assert(endptr == str); 557 + } 558 + 559 + static void test_qemu_strtoui_whitespace(void) 560 + { 561 + const char *str = " \t "; 562 + char f = 'X'; 563 + const char *endptr = &f; 564 + unsigned int res = 999; 565 + int err; 566 + 567 + err = qemu_strtoui(str, &endptr, 0, &res); 568 + 569 + g_assert_cmpint(err, ==, -EINVAL); 570 + g_assert(endptr == str); 571 + } 572 + 573 + static void test_qemu_strtoui_invalid(void) 574 + { 575 + const char *str = " xxxx \t abc"; 576 + char f = 'X'; 577 + const char *endptr = &f; 578 + unsigned int res = 999; 579 + int err; 580 + 581 + err = qemu_strtoui(str, &endptr, 0, &res); 582 + 583 + g_assert_cmpint(err, ==, -EINVAL); 584 + g_assert(endptr == str); 585 + } 586 + 587 + static void test_qemu_strtoui_trailing(void) 588 + { 589 + const char *str = "123xxx"; 590 + char f = 'X'; 591 + const char *endptr = &f; 592 + unsigned int res = 999; 593 + int err; 594 + 595 + err = qemu_strtoui(str, &endptr, 0, &res); 596 + 597 + g_assert_cmpint(err, ==, 0); 598 + g_assert_cmpuint(res, ==, 123); 599 + g_assert(endptr == str + 3); 600 + } 601 + 602 + static void test_qemu_strtoui_octal(void) 603 + { 604 + const char *str = "0123"; 605 + char f = 'X'; 606 + const char *endptr = &f; 607 + unsigned int res = 999; 608 + int err; 609 + 610 + err = qemu_strtoui(str, &endptr, 8, &res); 611 + 612 + g_assert_cmpint(err, ==, 0); 613 + g_assert_cmpuint(res, ==, 0123); 614 + g_assert(endptr == str + strlen(str)); 615 + 616 + res = 999; 617 + endptr = &f; 618 + err = qemu_strtoui(str, &endptr, 0, &res); 619 + 620 + g_assert_cmpint(err, ==, 0); 621 + g_assert_cmpuint(res, ==, 0123); 622 + g_assert(endptr == str + strlen(str)); 623 + } 624 + 625 + static void test_qemu_strtoui_decimal(void) 626 + { 627 + const char *str = "0123"; 628 + char f = 'X'; 629 + const char *endptr = &f; 630 + unsigned int res = 999; 631 + int err; 632 + 633 + err = qemu_strtoui(str, &endptr, 10, &res); 634 + 635 + g_assert_cmpint(err, ==, 0); 636 + g_assert_cmpuint(res, ==, 123); 637 + g_assert(endptr == str + strlen(str)); 638 + 639 + str = "123"; 640 + res = 999; 641 + endptr = &f; 642 + err = qemu_strtoui(str, &endptr, 0, &res); 643 + 644 + g_assert_cmpint(err, ==, 0); 645 + g_assert_cmpuint(res, ==, 123); 646 + g_assert(endptr == str + strlen(str)); 647 + } 648 + 649 + static void test_qemu_strtoui_hex(void) 650 + { 651 + const char *str = "0123"; 652 + char f = 'X'; 653 + const char *endptr = &f; 654 + unsigned int res = 999; 655 + int err; 656 + 657 + err = qemu_strtoui(str, &endptr, 16, &res); 658 + 659 + g_assert_cmpint(err, ==, 0); 660 + g_assert_cmphex(res, ==, 0x123); 661 + g_assert(endptr == str + strlen(str)); 662 + 663 + str = "0x123"; 664 + res = 999; 665 + endptr = &f; 666 + err = qemu_strtoui(str, &endptr, 0, &res); 667 + 668 + g_assert_cmpint(err, ==, 0); 669 + g_assert_cmphex(res, ==, 0x123); 670 + g_assert(endptr == str + strlen(str)); 671 + } 672 + 673 + static void test_qemu_strtoui_max(void) 674 + { 675 + char *str = g_strdup_printf("%u", UINT_MAX); 676 + char f = 'X'; 677 + const char *endptr = &f; 678 + unsigned int res = 999; 679 + int err; 680 + 681 + err = qemu_strtoui(str, &endptr, 0, &res); 682 + 683 + g_assert_cmpint(err, ==, 0); 684 + g_assert_cmphex(res, ==, UINT_MAX); 685 + g_assert(endptr == str + strlen(str)); 686 + g_free(str); 687 + } 688 + 689 + static void test_qemu_strtoui_overflow(void) 690 + { 691 + char *str = g_strdup_printf("%lld", (long long)UINT_MAX + 1ll); 692 + char f = 'X'; 693 + const char *endptr = &f; 694 + unsigned int res = 999; 695 + int err; 696 + 697 + err = qemu_strtoui(str, &endptr, 0, &res); 698 + 699 + g_assert_cmpint(err, ==, -ERANGE); 700 + g_assert_cmphex(res, ==, UINT_MAX); 701 + g_assert(endptr == str + strlen(str)); 702 + g_free(str); 703 + } 704 + 705 + static void test_qemu_strtoui_underflow(void) 706 + { 707 + char *str = g_strdup_printf("%lld", (long long)INT_MIN - 1ll); 708 + char f = 'X'; 709 + const char *endptr = &f; 710 + unsigned int res = 999; 711 + int err; 712 + 713 + err = qemu_strtoui(str, &endptr, 0, &res); 714 + 715 + g_assert_cmpint(err, ==, -ERANGE); 716 + g_assert_cmpuint(res, ==, (unsigned int)-1); 717 + g_assert(endptr == str + strlen(str)); 718 + g_free(str); 719 + } 720 + 721 + static void test_qemu_strtoui_negative(void) 722 + { 723 + const char *str = " \t -321"; 724 + char f = 'X'; 725 + const char *endptr = &f; 726 + unsigned int res = 999; 727 + int err; 728 + 729 + err = qemu_strtoui(str, &endptr, 0, &res); 730 + 731 + g_assert_cmpint(err, ==, 0); 732 + g_assert_cmpuint(res, ==, (unsigned int)-321); 733 + g_assert(endptr == str + strlen(str)); 734 + } 735 + 736 + static void test_qemu_strtoui_full_correct(void) 737 + { 738 + const char *str = "123"; 739 + unsigned int res = 999; 740 + int err; 741 + 742 + err = qemu_strtoui(str, NULL, 0, &res); 743 + 744 + g_assert_cmpint(err, ==, 0); 745 + g_assert_cmpuint(res, ==, 123); 746 + } 747 + 748 + static void test_qemu_strtoui_full_null(void) 749 + { 750 + unsigned int res = 999; 751 + int err; 752 + 753 + err = qemu_strtoui(NULL, NULL, 0, &res); 754 + 755 + g_assert_cmpint(err, ==, -EINVAL); 756 + } 757 + 758 + static void test_qemu_strtoui_full_empty(void) 759 + { 760 + const char *str = ""; 761 + unsigned int res = 999; 762 + int err; 763 + 764 + err = qemu_strtoui(str, NULL, 0, &res); 765 + 766 + g_assert_cmpint(err, ==, -EINVAL); 767 + } 768 + static void test_qemu_strtoui_full_negative(void) 769 + { 770 + const char *str = " \t -321"; 771 + unsigned int res = 999; 772 + int err; 773 + 774 + err = qemu_strtoui(str, NULL, 0, &res); 775 + g_assert_cmpint(err, ==, 0); 776 + g_assert_cmpuint(res, ==, (unsigned int)-321); 777 + } 778 + 779 + static void test_qemu_strtoui_full_trailing(void) 780 + { 781 + const char *str = "123xxx"; 782 + unsigned int res; 783 + int err; 784 + 785 + err = qemu_strtoui(str, NULL, 0, &res); 786 + 787 + g_assert_cmpint(err, ==, -EINVAL); 788 + } 789 + 790 + static void test_qemu_strtoui_full_max(void) 791 + { 792 + char *str = g_strdup_printf("%u", UINT_MAX); 793 + unsigned int res = 999; 794 + int err; 795 + 796 + err = qemu_strtoui(str, NULL, 0, &res); 797 + 798 + g_assert_cmpint(err, ==, 0); 799 + g_assert_cmphex(res, ==, UINT_MAX); 800 + g_free(str); 801 + } 802 + 226 803 static void test_qemu_strtol_correct(void) 227 804 { 228 805 const char *str = "12345 foo"; ··· 1611 2188 test_parse_uint_full_trailing); 1612 2189 g_test_add_func("/cutils/parse_uint_full/correct", 1613 2190 test_parse_uint_full_correct); 2191 + 2192 + /* qemu_strtoi() tests */ 2193 + g_test_add_func("/cutils/qemu_strtoi/correct", 2194 + test_qemu_strtoi_correct); 2195 + g_test_add_func("/cutils/qemu_strtoi/null", 2196 + test_qemu_strtoi_null); 2197 + g_test_add_func("/cutils/qemu_strtoi/empty", 2198 + test_qemu_strtoi_empty); 2199 + g_test_add_func("/cutils/qemu_strtoi/whitespace", 2200 + test_qemu_strtoi_whitespace); 2201 + g_test_add_func("/cutils/qemu_strtoi/invalid", 2202 + test_qemu_strtoi_invalid); 2203 + g_test_add_func("/cutils/qemu_strtoi/trailing", 2204 + test_qemu_strtoi_trailing); 2205 + g_test_add_func("/cutils/qemu_strtoi/octal", 2206 + test_qemu_strtoi_octal); 2207 + g_test_add_func("/cutils/qemu_strtoi/decimal", 2208 + test_qemu_strtoi_decimal); 2209 + g_test_add_func("/cutils/qemu_strtoi/hex", 2210 + test_qemu_strtoi_hex); 2211 + g_test_add_func("/cutils/qemu_strtoi/max", 2212 + test_qemu_strtoi_max); 2213 + g_test_add_func("/cutils/qemu_strtoi/overflow", 2214 + test_qemu_strtoi_overflow); 2215 + g_test_add_func("/cutils/qemu_strtoi/underflow", 2216 + test_qemu_strtoi_underflow); 2217 + g_test_add_func("/cutils/qemu_strtoi/negative", 2218 + test_qemu_strtoi_negative); 2219 + g_test_add_func("/cutils/qemu_strtoi_full/correct", 2220 + test_qemu_strtoi_full_correct); 2221 + g_test_add_func("/cutils/qemu_strtoi_full/null", 2222 + test_qemu_strtoi_full_null); 2223 + g_test_add_func("/cutils/qemu_strtoi_full/empty", 2224 + test_qemu_strtoi_full_empty); 2225 + g_test_add_func("/cutils/qemu_strtoi_full/negative", 2226 + test_qemu_strtoi_full_negative); 2227 + g_test_add_func("/cutils/qemu_strtoi_full/trailing", 2228 + test_qemu_strtoi_full_trailing); 2229 + g_test_add_func("/cutils/qemu_strtoi_full/max", 2230 + test_qemu_strtoi_full_max); 2231 + 2232 + /* qemu_strtoui() tests */ 2233 + g_test_add_func("/cutils/qemu_strtoui/correct", 2234 + test_qemu_strtoui_correct); 2235 + g_test_add_func("/cutils/qemu_strtoui/null", 2236 + test_qemu_strtoui_null); 2237 + g_test_add_func("/cutils/qemu_strtoui/empty", 2238 + test_qemu_strtoui_empty); 2239 + g_test_add_func("/cutils/qemu_strtoui/whitespace", 2240 + test_qemu_strtoui_whitespace); 2241 + g_test_add_func("/cutils/qemu_strtoui/invalid", 2242 + test_qemu_strtoui_invalid); 2243 + g_test_add_func("/cutils/qemu_strtoui/trailing", 2244 + test_qemu_strtoui_trailing); 2245 + g_test_add_func("/cutils/qemu_strtoui/octal", 2246 + test_qemu_strtoui_octal); 2247 + g_test_add_func("/cutils/qemu_strtoui/decimal", 2248 + test_qemu_strtoui_decimal); 2249 + g_test_add_func("/cutils/qemu_strtoui/hex", 2250 + test_qemu_strtoui_hex); 2251 + g_test_add_func("/cutils/qemu_strtoui/max", 2252 + test_qemu_strtoui_max); 2253 + g_test_add_func("/cutils/qemu_strtoui/overflow", 2254 + test_qemu_strtoui_overflow); 2255 + g_test_add_func("/cutils/qemu_strtoui/underflow", 2256 + test_qemu_strtoui_underflow); 2257 + g_test_add_func("/cutils/qemu_strtoui/negative", 2258 + test_qemu_strtoui_negative); 2259 + g_test_add_func("/cutils/qemu_strtoui_full/correct", 2260 + test_qemu_strtoui_full_correct); 2261 + g_test_add_func("/cutils/qemu_strtoui_full/null", 2262 + test_qemu_strtoui_full_null); 2263 + g_test_add_func("/cutils/qemu_strtoui_full/empty", 2264 + test_qemu_strtoui_full_empty); 2265 + g_test_add_func("/cutils/qemu_strtoui_full/negative", 2266 + test_qemu_strtoui_full_negative); 2267 + g_test_add_func("/cutils/qemu_strtoui_full/trailing", 2268 + test_qemu_strtoui_full_trailing); 2269 + g_test_add_func("/cutils/qemu_strtoui_full/max", 2270 + test_qemu_strtoui_full_max); 1614 2271 1615 2272 /* qemu_strtol() tests */ 1616 2273 g_test_add_func("/cutils/qemu_strtol/correct",
+109
util/cutils.c
··· 298 298 } 299 299 300 300 /** 301 + * Convert string @nptr to an integer, and store it in @result. 302 + * 303 + * This is a wrapper around strtol() that is harder to misuse. 304 + * Semantics of @nptr, @endptr, @base match strtol() with differences 305 + * noted below. 306 + * 307 + * @nptr may be null, and no conversion is performed then. 308 + * 309 + * If no conversion is performed, store @nptr in *@endptr and return 310 + * -EINVAL. 311 + * 312 + * If @endptr is null, and the string isn't fully converted, return 313 + * -EINVAL. This is the case when the pointer that would be stored in 314 + * a non-null @endptr points to a character other than '\0'. 315 + * 316 + * If the conversion overflows @result, store INT_MAX in @result, 317 + * and return -ERANGE. 318 + * 319 + * If the conversion underflows @result, store INT_MIN in @result, 320 + * and return -ERANGE. 321 + * 322 + * Else store the converted value in @result, and return zero. 323 + */ 324 + int qemu_strtoi(const char *nptr, const char **endptr, int base, 325 + int *result) 326 + { 327 + char *ep; 328 + long long lresult; 329 + 330 + if (!nptr) { 331 + if (endptr) { 332 + *endptr = nptr; 333 + } 334 + return -EINVAL; 335 + } 336 + 337 + errno = 0; 338 + lresult = strtoll(nptr, &ep, base); 339 + if (lresult < INT_MIN) { 340 + *result = INT_MIN; 341 + errno = ERANGE; 342 + } else if (lresult > INT_MAX) { 343 + *result = INT_MAX; 344 + errno = ERANGE; 345 + } else { 346 + *result = lresult; 347 + } 348 + return check_strtox_error(nptr, ep, endptr, errno); 349 + } 350 + 351 + /** 352 + * Convert string @nptr to an unsigned integer, and store it in @result. 353 + * 354 + * This is a wrapper around strtoul() that is harder to misuse. 355 + * Semantics of @nptr, @endptr, @base match strtoul() with differences 356 + * noted below. 357 + * 358 + * @nptr may be null, and no conversion is performed then. 359 + * 360 + * If no conversion is performed, store @nptr in *@endptr and return 361 + * -EINVAL. 362 + * 363 + * If @endptr is null, and the string isn't fully converted, return 364 + * -EINVAL. This is the case when the pointer that would be stored in 365 + * a non-null @endptr points to a character other than '\0'. 366 + * 367 + * If the conversion overflows @result, store UINT_MAX in @result, 368 + * and return -ERANGE. 369 + * 370 + * Else store the converted value in @result, and return zero. 371 + * 372 + * Note that a number with a leading minus sign gets converted without 373 + * the minus sign, checked for overflow (see above), then negated (in 374 + * @result's type). This is exactly how strtoul() works. 375 + */ 376 + int qemu_strtoui(const char *nptr, const char **endptr, int base, 377 + unsigned int *result) 378 + { 379 + char *ep; 380 + long long lresult; 381 + 382 + if (!nptr) { 383 + if (endptr) { 384 + *endptr = nptr; 385 + } 386 + return -EINVAL; 387 + } 388 + 389 + errno = 0; 390 + lresult = strtoull(nptr, &ep, base); 391 + 392 + /* Windows returns 1 for negative out-of-range values. */ 393 + if (errno == ERANGE) { 394 + *result = -1; 395 + } else { 396 + if (lresult > UINT_MAX) { 397 + *result = UINT_MAX; 398 + errno = ERANGE; 399 + } else if (lresult < INT_MIN) { 400 + *result = UINT_MAX; 401 + errno = ERANGE; 402 + } else { 403 + *result = lresult; 404 + } 405 + } 406 + return check_strtox_error(nptr, ep, endptr, errno); 407 + } 408 + 409 + /** 301 410 * Convert string @nptr to a long integer, and store it in @result. 302 411 * 303 412 * This is a wrapper around strtol() that is harder to misuse.