From 8837a7e357f38f065fc2059f054d0ace48d8a092 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Aug 2026 14:15:30 -0400 Subject: [PATCH 1/5] Add corpus of CVEs by type --- test/cve_corpus/cve_corpus_util.hpp | 39 ++++++++ ...e_2002_0391_cwe190_sunrpc_xdrarray_mul.cpp | 81 ++++++++++++++++ ...2002_0639_cwe190_openssh_challenge_mul.cpp | 95 +++++++++++++++++++ .../cve_2004_0657_cwe190_ntpd_offset_add.cpp | 81 ++++++++++++++++ ...cve_2004_0788_cwe190_gdkpixbuf_ico_mul.cpp | 81 ++++++++++++++++ ...2004_2013_cwe190_kernel_sctp_debug_mul.cpp | 81 ++++++++++++++++ ...e_2005_0102_cwe190_evolution_camel_mul.cpp | 81 ++++++++++++++++ .../cve_2005_1141_cwe190_gocr_pnm_mul.cpp | 81 ++++++++++++++++ ...ve_2005_1513_cwe190_qmail_stralloc_add.cpp | 81 ++++++++++++++++ .../cve_2005_2976_cwe190_gtk_xpm_mul.cpp | 81 ++++++++++++++++ .../cve_2006_3198_cwe190_opera_jpeg_mul.cpp | 81 ++++++++++++++++ .../cve_2006_4519_cwe190_gimp_dicom_mul.cpp | 80 ++++++++++++++++ ...cve_2007_0221_cwe190_exchange_imap_add.cpp | 81 ++++++++++++++++ .../cve_2007_2834_cwe190_ooo_tiff_mul.cpp | 81 ++++++++++++++++ .../cve_2007_2949_cwe190_gimp_psd_mul.cpp | 81 ++++++++++++++++ ...ve_2007_3387_cwe190_xpdf_predictor_mul.cpp | 81 ++++++++++++++++ ...ve_2007_4965_cwe190_python_imageop_mul.cpp | 81 ++++++++++++++++ .../cve_2007_6353_cwe190_exiv2_exif_mul.cpp | 81 ++++++++++++++++ .../cve_2008_1374_cwe190_cups_pdftops_mul.cpp | 81 ++++++++++++++++ ...ve_2008_2663_cwe190_ruby_ary_store_mul.cpp | 80 ++++++++++++++++ ...2008_2826_cwe190_kernel_sctp_addrs_mul.cpp | 81 ++++++++++++++++ .../cve_2008_4019_cwe190_excel_rept_mul.cpp | 81 ++++++++++++++++ .../cwe190/cve_2009_0723_cwe190_lcms_mul.cpp | 80 ++++++++++++++++ ...e_2009_0946_cwe190_freetype_smooth_mul.cpp | 80 ++++++++++++++++ .../cve_2010_3442_cwe190_kernel_alsa_mul.cpp | 80 ++++++++++++++++ .../cve_2011_1178_cwe190_gimp_pcx_mul.cpp | 80 ++++++++++++++++ ...12_1185_cwe190_imagemagick_profile_add.cpp | 80 ++++++++++++++++ .../cve_2013_7437_cwe190_potrace_bmp_mul.cpp | 81 ++++++++++++++++ .../cve_2014_4608_cwe190_kernel_lzo_add.cpp | 81 ++++++++++++++++ ...e_2015_1283_cwe190_expat_getbuffer_add.cpp | 90 ++++++++++++++++++ ...2018_13785_cwe190_libpng_width_bounded.cpp | 74 +++++++++++++++ ...4_0184_cwe191_tcpdump_isakmp_underflow.cpp | 76 +++++++++++++++ ...ve_2004_0816_cwe191_iptables_underflow.cpp | 77 +++++++++++++++ ...e_2004_1002_cwe191_pppd_cbcp_underflow.cpp | 76 +++++++++++++++ ...2005_0199_cwe191_ngircd_mask_underflow.cpp | 76 +++++++++++++++ ...cve_2009_3301_cwe191_ooo_ww8_underflow.cpp | 77 +++++++++++++++ ...0_2497_cwe191_freetype_glyph_underflow.cpp | 76 +++++++++++++++ ..._2010_4164_cwe191_kernel_x25_underflow.cpp | 77 +++++++++++++++ ...2010_4529_cwe191_kernel_irda_underflow.cpp | 77 +++++++++++++++ ...2011_1770_cwe191_kernel_dccp_underflow.cpp | 76 +++++++++++++++ ...011_2497_cwe191_kernel_l2cap_underflow.cpp | 76 +++++++++++++++ ...11_4031_cwe191_ffmpeg_asfrtp_underflow.cpp | 76 +++++++++++++++ ...3_6424_cwe191_xorg_trapezoid_underflow.cpp | 76 +++++++++++++++ ...6425_cwe191_pixman_trapezoid_underflow.cpp | 76 +++++++++++++++ .../cve_2014_0497_cwe191_flash_underflow.cpp | 77 +++++++++++++++ ...4_8768_cwe191_tcpdump_geonet_underflow.cpp | 77 +++++++++++++++ ...2014_9087_cwe191_libksba_oid_underflow.cpp | 75 +++++++++++++++ ...e_2015_0537_cwe191_rsa_bsafe_underflow.cpp | 77 +++++++++++++++ ..._2015_1208_cwe191_ffmpeg_mov_underflow.cpp | 77 +++++++++++++++ ...e_2015_2311_cwe191_capnproto_underflow.cpp | 77 +++++++++++++++ ...2015_5212_cwe191_libreoffice_underflow.cpp | 77 +++++++++++++++ ...16_10166_cwe191_libgd_interp_underflow.cpp | 77 +++++++++++++++ ..._10268_cwe191_libtiff_tiffcp_underflow.cpp | 77 +++++++++++++++ ..._2016_1925_cwe191_lha_header_underflow.cpp | 77 +++++++++++++++ ...0_cwe191_graphicsmagick_meta_underflow.cpp | 77 +++++++++++++++ ...ve_2017_14496_cwe191_dnsmasq_underflow.cpp | 77 +++++++++++++++ ..._15874_cwe191_busybox_unlzma_underflow.cpp | 77 +++++++++++++++ ...7_6313_cwe191_gdkpixbuf_icns_underflow.cpp | 77 +++++++++++++++ .../cve_2017_8911_cwe191_tnef_underflow.cpp | 77 +++++++++++++++ ...017_8924_cwe191_kernel_io_ti_underflow.cpp | 77 +++++++++++++++ ...2017_9214_cwe191_openvswitch_underflow.cpp | 77 +++++++++++++++ ...04_0804_cwe369_libtiff_dirread_divzero.cpp | 75 +++++++++++++++ .../cve_2009_1887_cwe369_netsnmp_divzero.cpp | 75 +++++++++++++++ ...ve_2011_1012_cwe369_kernel_ldm_modzero.cpp | 75 +++++++++++++++ ...e_2012_0207_cwe369_kernel_igmp_modzero.cpp | 75 +++++++++++++++ ...ve_2014_9756_cwe369_libsndfile_divzero.cpp | 80 ++++++++++++++++ ...2015_3418_cwe369_xorg_putimage_divzero.cpp | 76 +++++++++++++++ .../cve_2015_6855_cwe369_qemu_ide_divzero.cpp | 75 +++++++++++++++ ...ve_2015_7513_cwe369_kernel_kvm_divzero.cpp | 76 +++++++++++++++ ..._10053_cwe369_imagemagick_tiff_divzero.cpp | 76 +++++++++++++++ ...9_cwe369_ghostscript_intersect_divzero.cpp | 76 +++++++++++++++ ...016_10266_cwe369_libtiff_10266_divzero.cpp | 76 +++++++++++++++ ...016_10267_cwe369_libtiff_10267_divzero.cpp | 76 +++++++++++++++ ...16_3622_cwe369_libtiff_predict_divzero.cpp | 75 +++++++++++++++ ..._3623_cwe369_libtiff_rgb2ycbcr_divzero.cpp | 75 +++++++++++++++ ..._2016_4797_cwe369_openjpeg_tcd_divzero.cpp | 76 +++++++++++++++ ..._2016_5323_cwe369_libtiff_fax3_divzero.cpp | 76 +++++++++++++++ ...6505_cwe369_wireshark_packetbb_divzero.cpp | 75 +++++++++++++++ ..._2016_7499_cwe369_libav_aacsbr_divzero.cpp | 76 +++++++++++++++ ...e_2016_8667_cwe369_qemu_rc4030_divzero.cpp | 76 +++++++++++++++ ...e_2016_8669_cwe369_qemu_serial_divzero.cpp | 76 +++++++++++++++ ...ve_2016_8691_cwe369_jasper_siz_divzero.cpp | 76 +++++++++++++++ ...2016_8697_cwe369_potrace_bmnew_divzero.cpp | 76 +++++++++++++++ .../cve_2016_9112_cwe369_openjpeg_divzero.cpp | 75 +++++++++++++++ ...e_2016_9265_cwe369_libming_mp3_divzero.cpp | 76 +++++++++++++++ ...e_2016_9922_cwe369_qemu_cirrus_divzero.cpp | 76 +++++++++++++++ ..._6833_cwe369_audiofile_runpull_divzero.cpp | 76 +++++++++++++++ ...7_6835_cwe369_audiofile_reset1_divzero.cpp | 76 +++++++++++++++ ...cve_2017_7448_cwe369_lepton_fb_divzero.cpp | 76 +++++++++++++++ ..._2017_7595_cwe369_libtiff_jpeg_divzero.cpp | 76 +++++++++++++++ ..._7962_cwe369_imageworsener_gif_divzero.cpp | 76 +++++++++++++++ ..._2007_4268_cwe681_apple_net_signedness.cpp | 48 ++++++++++ ...008_1721_cwe681_python_zlib_signedness.cpp | 48 ++++++++++ ...009_0231_cwe681_windows_eot_signedness.cpp | 48 ++++++++++ ...406_cwe681_module_signature_signedness.cpp | 48 ++++++++++ ..._cve_2016_3074_cwe681_libgd_signedness.cpp | 48 ++++++++++ ...e_2018_1000224_cwe681_godot_signedness.cpp | 48 ++++++++++ ...18_11262_cwe681_android_qrd_signedness.cpp | 48 ++++++++++ ...8_5251_cwe681_libming_sbits_signedness.cpp | 49 ++++++++++ ..._2018_5711_cwe681_libgd_gif_signedness.cpp | 48 ++++++++++ ...010204_cwe681_binutils_gold_signedness.cpp | 48 ++++++++++ ...l_cve_2019_14842_cwe681_nbd_signedness.cpp | 48 ++++++++++ ...19945_cwe681_openwrt_uhttpd_signedness.cpp | 49 ++++++++++ ...19_7310_cwe681_poppler_xref_signedness.cpp | 48 ++++++++++ ...2020_13545_cwe681_textmaker_signedness.cpp | 48 ++++++++++ ...cve_2020_1913_cwe681_hermes_signedness.cpp | 48 ++++++++++ ...27219_cwe681_glib_bytearray_signedness.cpp | 48 ++++++++++ ...27882_cwe681_openbsd_slaacd_signedness.cpp | 48 ++++++++++ ...282_cwe681_openoffice_alloc_truncation.cpp | 74 +++++++++++++++ ...2140_cwe681_imagemagick_dcm_truncation.cpp | 75 +++++++++++++++ ...7308_cwe681_kernel_afpacket_truncation.cpp | 74 +++++++++++++++ ...8_3999_cwe681_atlantis_jpeg_truncation.cpp | 75 +++++++++++++++ ..._8786_cwe681_freerdp_bitmap_truncation.cpp | 77 +++++++++++++++ ...2019_10624_cwe681_libiec_u8_truncation.cpp | 74 +++++++++++++++ .../cve_2019_14563_cwe681_edk2_truncation.cpp | 75 +++++++++++++++ ...778_cwe681_tensorflow_index_truncation.cpp | 75 +++++++++++++++ ...019_19958_cwe681_libiec_str_truncation.cpp | 75 +++++++++++++++ ...2_cwe681_freerdp_updaterecv_truncation.cpp | 75 +++++++++++++++ ...21_21860_cwe681_mpeg4_21860_truncation.cpp | 75 +++++++++++++++ ...21_21861_cwe681_mpeg4_21861_truncation.cpp | 75 +++++++++++++++ ...1_36357_cwe681_openpower_ts_truncation.cpp | 75 +++++++++++++++ ...e_2011_1573_cwe682_kernel_sctp_bounded.cpp | 77 +++++++++++++++ ..._2011_3062_cwe682_ots_offbyone_bounded.cpp | 82 ++++++++++++++++ ...2016_7433_cwe682_ntp_calc_notprevented.cpp | 70 ++++++++++++++ ..._11537_cwe682_imagemagick_palm_divzero.cpp | 65 +++++++++++++ ...2017_8326_cwe682_imageworsener_shl_shl.cpp | 67 +++++++++++++ ..._2017_8932_cwe682_go_p256_notprevented.cpp | 66 +++++++++++++ ...ve_2018_11790_cwe682_apache_oo_bounded.cpp | 76 +++++++++++++++ ...e_2018_14439_cwe682_eos4j_notprevented.cpp | 66 +++++++++++++ .../cve_2018_16781_cwe682_ffjpeg_divzero.cpp | 65 +++++++++++++ ...e_2018_20999_cwe682_orion_notprevented.cpp | 66 +++++++++++++ 131 files changed, 9544 insertions(+) create mode 100644 test/cve_corpus/cve_corpus_util.hpp create mode 100644 test/cve_corpus/cwe190/cve_2002_0391_cwe190_sunrpc_xdrarray_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2002_0639_cwe190_openssh_challenge_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2004_0657_cwe190_ntpd_offset_add.cpp create mode 100644 test/cve_corpus/cwe190/cve_2004_0788_cwe190_gdkpixbuf_ico_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2004_2013_cwe190_kernel_sctp_debug_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2005_0102_cwe190_evolution_camel_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2005_1141_cwe190_gocr_pnm_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2005_1513_cwe190_qmail_stralloc_add.cpp create mode 100644 test/cve_corpus/cwe190/cve_2005_2976_cwe190_gtk_xpm_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2006_3198_cwe190_opera_jpeg_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2006_4519_cwe190_gimp_dicom_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2007_0221_cwe190_exchange_imap_add.cpp create mode 100644 test/cve_corpus/cwe190/cve_2007_2834_cwe190_ooo_tiff_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2007_2949_cwe190_gimp_psd_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2007_3387_cwe190_xpdf_predictor_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2007_4965_cwe190_python_imageop_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2007_6353_cwe190_exiv2_exif_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2008_1374_cwe190_cups_pdftops_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2008_2663_cwe190_ruby_ary_store_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2008_2826_cwe190_kernel_sctp_addrs_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2008_4019_cwe190_excel_rept_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2009_0723_cwe190_lcms_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2009_0946_cwe190_freetype_smooth_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2010_3442_cwe190_kernel_alsa_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2011_1178_cwe190_gimp_pcx_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2012_1185_cwe190_imagemagick_profile_add.cpp create mode 100644 test/cve_corpus/cwe190/cve_2013_7437_cwe190_potrace_bmp_mul.cpp create mode 100644 test/cve_corpus/cwe190/cve_2014_4608_cwe190_kernel_lzo_add.cpp create mode 100644 test/cve_corpus/cwe190/cve_2015_1283_cwe190_expat_getbuffer_add.cpp create mode 100644 test/cve_corpus/cwe190/cve_2018_13785_cwe190_libpng_width_bounded.cpp create mode 100644 test/cve_corpus/cwe191/cve_2004_0184_cwe191_tcpdump_isakmp_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2004_0816_cwe191_iptables_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2004_1002_cwe191_pppd_cbcp_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2005_0199_cwe191_ngircd_mask_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2009_3301_cwe191_ooo_ww8_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2010_2497_cwe191_freetype_glyph_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2010_4164_cwe191_kernel_x25_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2010_4529_cwe191_kernel_irda_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2011_1770_cwe191_kernel_dccp_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2011_2497_cwe191_kernel_l2cap_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2011_4031_cwe191_ffmpeg_asfrtp_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2013_6424_cwe191_xorg_trapezoid_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2013_6425_cwe191_pixman_trapezoid_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2014_0497_cwe191_flash_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2014_8768_cwe191_tcpdump_geonet_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2014_9087_cwe191_libksba_oid_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2015_0537_cwe191_rsa_bsafe_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2015_1208_cwe191_ffmpeg_mov_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2015_2311_cwe191_capnproto_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2015_5212_cwe191_libreoffice_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2016_10166_cwe191_libgd_interp_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2016_10268_cwe191_libtiff_tiffcp_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2016_1925_cwe191_lha_header_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2016_7800_cwe191_graphicsmagick_meta_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2017_14496_cwe191_dnsmasq_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2017_15874_cwe191_busybox_unlzma_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2017_6313_cwe191_gdkpixbuf_icns_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2017_8911_cwe191_tnef_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2017_8924_cwe191_kernel_io_ti_underflow.cpp create mode 100644 test/cve_corpus/cwe191/cve_2017_9214_cwe191_openvswitch_underflow.cpp create mode 100644 test/cve_corpus/cwe369/cve_2004_0804_cwe369_libtiff_dirread_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2009_1887_cwe369_netsnmp_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2011_1012_cwe369_kernel_ldm_modzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2012_0207_cwe369_kernel_igmp_modzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2014_9756_cwe369_libsndfile_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2015_3418_cwe369_xorg_putimage_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2015_6855_cwe369_qemu_ide_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2015_7513_cwe369_kernel_kvm_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_10053_cwe369_imagemagick_tiff_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_10219_cwe369_ghostscript_intersect_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_10266_cwe369_libtiff_10266_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_10267_cwe369_libtiff_10267_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_3622_cwe369_libtiff_predict_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_3623_cwe369_libtiff_rgb2ycbcr_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_4797_cwe369_openjpeg_tcd_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_5323_cwe369_libtiff_fax3_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_6505_cwe369_wireshark_packetbb_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_7499_cwe369_libav_aacsbr_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_8667_cwe369_qemu_rc4030_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_8669_cwe369_qemu_serial_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_8691_cwe369_jasper_siz_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_8697_cwe369_potrace_bmnew_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_9112_cwe369_openjpeg_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_9265_cwe369_libming_mp3_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2016_9922_cwe369_qemu_cirrus_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2017_6833_cwe369_audiofile_runpull_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2017_6835_cwe369_audiofile_reset1_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2017_7448_cwe369_lepton_fb_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2017_7595_cwe369_libtiff_jpeg_divzero.cpp create mode 100644 test/cve_corpus/cwe369/cve_2017_7962_cwe369_imageworsener_gif_divzero.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2007_4268_cwe681_apple_net_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2008_1721_cwe681_python_zlib_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2009_0231_cwe681_windows_eot_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2015_3406_cwe681_module_signature_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2016_3074_cwe681_libgd_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2018_1000224_cwe681_godot_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2018_11262_cwe681_android_qrd_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2018_5251_cwe681_libming_sbits_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2018_5711_cwe681_libgd_gif_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2019_1010204_cwe681_binutils_gold_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2019_14842_cwe681_nbd_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2019_19945_cwe681_openwrt_uhttpd_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2019_7310_cwe681_poppler_xref_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2020_13545_cwe681_textmaker_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2020_1913_cwe681_hermes_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2021_27219_cwe681_glib_bytearray_signedness.cpp create mode 100644 test/cve_corpus/cwe681/compile_fail_cve_2022_27882_cwe681_openbsd_slaacd_signedness.cpp create mode 100644 test/cve_corpus/cwe681/cve_2008_3282_cwe681_openoffice_alloc_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2017_12140_cwe681_imagemagick_dcm_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2017_7308_cwe681_kernel_afpacket_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2018_3999_cwe681_atlantis_jpeg_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2018_8786_cwe681_freerdp_bitmap_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2019_10624_cwe681_libiec_u8_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2019_14563_cwe681_edk2_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2019_16778_cwe681_tensorflow_index_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2019_19958_cwe681_libiec_str_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2020_4032_cwe681_freerdp_updaterecv_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2021_21860_cwe681_mpeg4_21860_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2021_21861_cwe681_mpeg4_21861_truncation.cpp create mode 100644 test/cve_corpus/cwe681/cve_2021_36357_cwe681_openpower_ts_truncation.cpp create mode 100644 test/cve_corpus/cwe682/cve_2011_1573_cwe682_kernel_sctp_bounded.cpp create mode 100644 test/cve_corpus/cwe682/cve_2011_3062_cwe682_ots_offbyone_bounded.cpp create mode 100644 test/cve_corpus/cwe682/cve_2016_7433_cwe682_ntp_calc_notprevented.cpp create mode 100644 test/cve_corpus/cwe682/cve_2017_11537_cwe682_imagemagick_palm_divzero.cpp create mode 100644 test/cve_corpus/cwe682/cve_2017_8326_cwe682_imageworsener_shl_shl.cpp create mode 100644 test/cve_corpus/cwe682/cve_2017_8932_cwe682_go_p256_notprevented.cpp create mode 100644 test/cve_corpus/cwe682/cve_2018_11790_cwe682_apache_oo_bounded.cpp create mode 100644 test/cve_corpus/cwe682/cve_2018_14439_cwe682_eos4j_notprevented.cpp create mode 100644 test/cve_corpus/cwe682/cve_2018_16781_cwe682_ffjpeg_divzero.cpp create mode 100644 test/cve_corpus/cwe682/cve_2018_20999_cwe682_orion_notprevented.cpp diff --git a/test/cve_corpus/cve_corpus_util.hpp b/test/cve_corpus/cve_corpus_util.hpp new file mode 100644 index 0000000..74c2eaf --- /dev/null +++ b/test/cve_corpus/cve_corpus_util.hpp @@ -0,0 +1,39 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_SAFE_NUMBERS_TEST_CVE_CORPUS_UTIL_HPP +#define BOOST_SAFE_NUMBERS_TEST_CVE_CORPUS_UTIL_HPP + +#include + +// Ground truth for the native-reproduction arm, computed in a wider type so the +// differential assertion never itself overflows and never trips -Wconversion or +// -Wsign-conversion. These are NOT the code under test; they only establish the +// mathematically correct value that the wrapped native result is compared against. +// Files whose root cause width is u64 compute their ground truth inline with a +// 128-bit type (reachable through ), since this header +// deliberately depends only on . +namespace cve_corpus { + +// The true 64-bit product of two 32-bit values (widening is value-preserving). +[[nodiscard]] constexpr std::uint64_t true_mul(std::uint32_t a, std::uint32_t b) noexcept +{ + return static_cast(a) * static_cast(b); +} + +// The true 64-bit sum of two 32-bit values. +[[nodiscard]] constexpr std::uint64_t true_add(std::uint32_t a, std::uint32_t b) noexcept +{ + return static_cast(a) + static_cast(b); +} + +// The true signed 64-bit difference of two 32-bit signed values. +[[nodiscard]] constexpr std::int64_t true_sub(std::int32_t a, std::int32_t b) noexcept +{ + return static_cast(a) - static_cast(b); +} + +} // namespace cve_corpus + +#endif // BOOST_SAFE_NUMBERS_TEST_CVE_CORPUS_UTIL_HPP diff --git a/test/cve_corpus/cwe190/cve_2002_0391_cwe190_sunrpc_xdrarray_mul.cpp b/test/cve_corpus/cwe190/cve_2002_0391_cwe190_sunrpc_xdrarray_mul.cpp new file mode 100644 index 0000000..e4e1e6f --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2002_0391_cwe190_sunrpc_xdrarray_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2002-0391 +// cwe: CWE-190 +// product: SunRPC xdr_array (glibc) +// version: before the 2002 fix +// summary: Integer overflow in SunRPC xdr_array (glibc). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=600000000, element_size=8 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2002-0391 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Element count times element size overflows in xdr_array. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {600000000U}; + const std::uint32_t element_size {8U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t bytes {static_cast(count * element_size)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 505032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {600000000U}; + const u32 element_size {8U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2002_0639_cwe190_openssh_challenge_mul.cpp b/test/cve_corpus/cwe190/cve_2002_0639_cwe190_openssh_challenge_mul.cpp new file mode 100644 index 0000000..2ab86e1 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2002_0639_cwe190_openssh_challenge_mul.cpp @@ -0,0 +1,95 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2002-0639 +// cwe: CWE-190 +// product: OpenSSH +// version: 2.9.9 through 3.3 +// summary: Integer overflow in sshd challenge-response auth allows remote code execution. +// root-cause: unsigned multiplication (nresp * sizeof(char*)) in the response array size +// root-cause-width: u32 +// trigger: nresp=1073741824, element_size=4 (pointer size on a 32-bit target) +// consequence: heap buffer overflow (xmalloc(0) then writes nresp pointers) +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2002-0639 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Attacker sends a large nresp; response = xmalloc(nresp * sizeof(char*)) +// notes: wraps to 0 on a 32-bit target, then the loop writes nresp pointers. +// notes: Modeled at u32 width; the wrapped product is exactly 0. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +// Native fixed-width types silently wrap: the response-array byte count wraps to +// zero, xmalloc(0) under-allocates, and the subsequent loop writes nresp pointers +// past the end of the buffer. +void native_reproduction() +{ + const std::uint32_t nresp {1073741824U}; // 2^30, attacker controlled + const std::uint32_t element_size {4U}; // sizeof(char*) on a 32-bit target + + // Ground truth in a wider type: 2^30 * 4 == 2^32 == 4294967296. + const std::uint64_t true_total {cve_corpus::true_mul(nresp, element_size)}; + + // The vulnerable 32-bit computation. The explicit cast documents the intended + // 32-bit wraparound and keeps the line clean under -Wconversion. + const std::uint32_t total_bytes {static_cast(nresp * element_size)}; + + BOOST_TEST(true_total > static_cast(nresp)); // real size exceeds the count + BOOST_TEST_EQ(total_bytes, 0U); // native product wraps to zero + BOOST_TEST(static_cast(total_bytes) != true_total); // silently wrong value + BOOST_TEST(total_bytes < nresp); // buffer smaller than element count +} + +// The identical expression in safe types throws at the faulting multiply, before +// any allocation can be made from the wrong size. +void safe_reproduction() +{ + const u32 nresp {1073741824U}; + const u32 element_size {4U}; + + BOOST_TEST_THROWS((void)(nresp * element_size), std::overflow_error); + + // Non-throwing oracle arm (noexcept): checked_mul returns nullopt on the fault, + // so a caller can branch on the error instead of catching. + BOOST_TEST(!checked_mul(nresp, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2004_0657_cwe190_ntpd_offset_add.cpp b/test/cve_corpus/cwe190/cve_2004_0657_cwe190_ntpd_offset_add.cpp new file mode 100644 index 0000000..66fe12d --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2004_0657_cwe190_ntpd_offset_add.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2004-0657 +// cwe: CWE-190 +// product: NTP daemon (ntpd) +// version: ntpd before 4.0 +// summary: Integer overflow in NTP daemon (ntpd). +// root-cause: unsigned addition of two values +// root-cause-width: u32 +// trigger: first=2500000000, second=2000000000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2004-0657 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Time offset accumulation overflows. +// notes: Modeled at the canonical addition overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t first {2500000000U}; + const std::uint32_t second {2000000000U}; + + const std::uint64_t true_total {cve_corpus::true_add(first, second)}; + const std::uint32_t total {static_cast(first + second)}; + + BOOST_TEST(true_total > static_cast(first)); + BOOST_TEST_EQ(total, 205032704U); + BOOST_TEST(static_cast(total) < true_total); +} + +void safe_reproduction() +{ + const u32 first {2500000000U}; + const u32 second {2000000000U}; + + BOOST_TEST_THROWS((void)(first + second), std::overflow_error); + BOOST_TEST(!checked_add(first, second).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2004_0788_cwe190_gdkpixbuf_ico_mul.cpp b/test/cve_corpus/cwe190/cve_2004_0788_cwe190_gdkpixbuf_ico_mul.cpp new file mode 100644 index 0000000..8a3fe9f --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2004_0788_cwe190_gdkpixbuf_ico_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2004-0788 +// cwe: CWE-190 +// product: gdk-pixbuf ICO decoder +// version: gdk-pixbuf before 0.22 +// summary: Integer overflow in gdk-pixbuf ICO decoder. +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: width=70000, height=70000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2004-0788 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: ICO image dimensions overflow the pixel count. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {70000U}; + const std::uint32_t height {70000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 605032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {70000U}; + const u32 height {70000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2004_2013_cwe190_kernel_sctp_debug_mul.cpp b/test/cve_corpus/cwe190/cve_2004_2013_cwe190_kernel_sctp_debug_mul.cpp new file mode 100644 index 0000000..c979a2c --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2004_2013_cwe190_kernel_sctp_debug_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2004-2013 +// cwe: CWE-190 +// product: Linux kernel SCTP (SCTP_SOCKOPT_DEBUG_NAME) +// version: Linux 2.4.25 +// summary: Integer overflow in Linux kernel SCTP (SCTP_SOCKOPT_DEBUG_NAME). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=400000000, element_size=12 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2004-2013 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Option length count times size overflows. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {400000000U}; + const std::uint32_t element_size {12U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t bytes {static_cast(count * element_size)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 505032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {400000000U}; + const u32 element_size {12U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2005_0102_cwe190_evolution_camel_mul.cpp b/test/cve_corpus/cwe190/cve_2005_0102_cwe190_evolution_camel_mul.cpp new file mode 100644 index 0000000..d0c4cb4 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2005_0102_cwe190_evolution_camel_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2005-0102 +// cwe: CWE-190 +// product: Evolution (camel-lock-helper) +// version: Evolution 2.0.2 and earlier +// summary: Integer overflow in Evolution (camel-lock-helper). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=200000000, element_size=24 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2005-0102 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Response size count times element size overflows. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {200000000U}; + const std::uint32_t element_size {24U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t bytes {static_cast(count * element_size)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 505032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {200000000U}; + const u32 element_size {24U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2005_1141_cwe190_gocr_pnm_mul.cpp b/test/cve_corpus/cwe190/cve_2005_1141_cwe190_gocr_pnm_mul.cpp new file mode 100644 index 0000000..66cdf8b --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2005_1141_cwe190_gocr_pnm_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2005-1141 +// cwe: CWE-190 +// product: GOCR (readpgm in pnm.c) +// version: GOCR 0.40 +// summary: Integer overflow in GOCR (readpgm in pnm.c). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: width=85000, height=85000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2005-1141 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: PNM image dimensions overflow the pixel count. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {85000U}; + const std::uint32_t height {85000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 2930032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {85000U}; + const u32 height {85000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2005_1513_cwe190_qmail_stralloc_add.cpp b/test/cve_corpus/cwe190/cve_2005_1513_cwe190_qmail_stralloc_add.cpp new file mode 100644 index 0000000..7b1f632 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2005_1513_cwe190_qmail_stralloc_add.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2005-1513 +// cwe: CWE-190 +// product: qmail (stralloc_readyplus, 64-bit) +// version: qmail on 64-bit +// summary: Integer overflow in qmail (stralloc_readyplus, 64-bit). +// root-cause: unsigned addition of two values +// root-cause-width: u32 +// trigger: first=4000000000, second=500000000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2005-1513 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Buffer length plus growth overflows on 64-bit. +// notes: Modeled at the canonical addition overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t first {4000000000U}; + const std::uint32_t second {500000000U}; + + const std::uint64_t true_total {cve_corpus::true_add(first, second)}; + const std::uint32_t total {static_cast(first + second)}; + + BOOST_TEST(true_total > static_cast(first)); + BOOST_TEST_EQ(total, 205032704U); + BOOST_TEST(static_cast(total) < true_total); +} + +void safe_reproduction() +{ + const u32 first {4000000000U}; + const u32 second {500000000U}; + + BOOST_TEST_THROWS((void)(first + second), std::overflow_error); + BOOST_TEST(!checked_add(first, second).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2005_2976_cwe190_gtk_xpm_mul.cpp b/test/cve_corpus/cwe190/cve_2005_2976_cwe190_gtk_xpm_mul.cpp new file mode 100644 index 0000000..ef6e56c --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2005_2976_cwe190_gtk_xpm_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2005-2976 +// cwe: CWE-190 +// product: GTK+ gdk-pixbuf (io-xpm.c) +// version: GTK+ before 2.8.7 +// summary: Integer overflow in GTK+ gdk-pixbuf (io-xpm.c). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: width=75000, height=75000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2005-2976 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: XPM image dimensions overflow the pixel count. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {75000U}; + const std::uint32_t height {75000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 1330032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {75000U}; + const u32 height {75000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2006_3198_cwe190_opera_jpeg_mul.cpp b/test/cve_corpus/cwe190/cve_2006_3198_cwe190_opera_jpeg_mul.cpp new file mode 100644 index 0000000..b909014 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2006_3198_cwe190_opera_jpeg_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2006-3198 +// cwe: CWE-190 +// product: Opera (JPEG handling) +// version: Opera 8.54 and earlier +// summary: Integer overflow in Opera (JPEG handling). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: width=60000, height=80000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2006-3198 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: JPEG image dimensions overflow the pixel count. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {60000U}; + const std::uint32_t height {80000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 505032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {60000U}; + const u32 height {80000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2006_4519_cwe190_gimp_dicom_mul.cpp b/test/cve_corpus/cwe190/cve_2006_4519_cwe190_gimp_dicom_mul.cpp new file mode 100644 index 0000000..0d44040 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2006_4519_cwe190_gimp_dicom_mul.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2006-4519 +// cwe: CWE-190 +// product: GIMP image loader plugins (DICOM) +// version: before 2.2.16 +// summary: Integer overflow from crafted DICOM length values. +// root-cause: unsigned multiplication (width * height) of image dimensions +// root-cause-width: u32 +// trigger: width=80000, height=80000 +// consequence: undersized allocation then code execution +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2006-4519 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: The DICOM loader multiplies attacker controlled dimensions at u32 width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {80000U}; + const std::uint32_t height {80000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 2105032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {80000U}; + const u32 height {80000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2007_0221_cwe190_exchange_imap_add.cpp b/test/cve_corpus/cwe190/cve_2007_0221_cwe190_exchange_imap_add.cpp new file mode 100644 index 0000000..c973f8f --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2007_0221_cwe190_exchange_imap_add.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2007-0221 +// cwe: CWE-190 +// product: Microsoft Exchange (IMAP) +// version: Exchange 2000 SP3 +// summary: Integer overflow in Microsoft Exchange (IMAP). +// root-cause: unsigned addition of two values +// root-cause-width: u32 +// trigger: first=3000000000, second=1500000000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2007-0221 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: IMAP command length accumulation overflows. +// notes: Modeled at the canonical addition overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t first {3000000000U}; + const std::uint32_t second {1500000000U}; + + const std::uint64_t true_total {cve_corpus::true_add(first, second)}; + const std::uint32_t total {static_cast(first + second)}; + + BOOST_TEST(true_total > static_cast(first)); + BOOST_TEST_EQ(total, 205032704U); + BOOST_TEST(static_cast(total) < true_total); +} + +void safe_reproduction() +{ + const u32 first {3000000000U}; + const u32 second {1500000000U}; + + BOOST_TEST_THROWS((void)(first + second), std::overflow_error); + BOOST_TEST(!checked_add(first, second).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2007_2834_cwe190_ooo_tiff_mul.cpp b/test/cve_corpus/cwe190/cve_2007_2834_cwe190_ooo_tiff_mul.cpp new file mode 100644 index 0000000..18704ac --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2007_2834_cwe190_ooo_tiff_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2007-2834 +// cwe: CWE-190 +// product: OpenOffice.org TIFF parser +// version: OpenOffice.org before 2.3 +// summary: Integer overflow in OpenOffice.org TIFF parser. +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: width=66000, height=66000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2007-2834 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: TIFF image dimensions overflow the pixel count. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {66000U}; + const std::uint32_t height {66000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 61032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {66000U}; + const u32 height {66000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2007_2949_cwe190_gimp_psd_mul.cpp b/test/cve_corpus/cwe190/cve_2007_2949_cwe190_gimp_psd_mul.cpp new file mode 100644 index 0000000..a06521e --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2007_2949_cwe190_gimp_psd_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2007-2949 +// cwe: CWE-190 +// product: GIMP PSD plugin +// version: GIMP 2.2.15 +// summary: Integer overflow in GIMP PSD plugin. +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=1000000000, element_size=5 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2007-2949 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: PSD pixel data size overflows. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {1000000000U}; + const std::uint32_t element_size {5U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t bytes {static_cast(count * element_size)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 705032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {1000000000U}; + const u32 element_size {5U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2007_3387_cwe190_xpdf_predictor_mul.cpp b/test/cve_corpus/cwe190/cve_2007_3387_cwe190_xpdf_predictor_mul.cpp new file mode 100644 index 0000000..803a331 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2007_3387_cwe190_xpdf_predictor_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2007-3387 +// cwe: CWE-190 +// product: xpdf StreamPredictor +// version: xpdf 3.02 +// summary: Integer overflow in xpdf StreamPredictor. +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: width=100000, height=100000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2007-3387 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Predictor row size overflows from crafted width and components. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {100000U}; + const std::uint32_t height {100000U}; + + const std::uint64_t true_cells {cve_corpus::true_mul(width, height)}; + const std::uint32_t cells {static_cast(width * height)}; + + BOOST_TEST(true_cells > static_cast(width)); + BOOST_TEST_EQ(cells, 1410065408U); + BOOST_TEST(static_cast(cells) < true_cells); +} + +void safe_reproduction() +{ + const u32 width {100000U}; + const u32 height {100000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2007_4965_cwe190_python_imageop_mul.cpp b/test/cve_corpus/cwe190/cve_2007_4965_cwe190_python_imageop_mul.cpp new file mode 100644 index 0000000..3cb66bb --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2007_4965_cwe190_python_imageop_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2007-4965 +// cwe: CWE-190 +// product: Python (imageop module) +// version: Python 2.5.1 and earlier +// summary: Integer overflow in Python (imageop module). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: width=90000, height=90000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2007-4965 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Image dimensions overflow the pixel count in imageop. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {90000U}; + const std::uint32_t height {90000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 3805032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {90000U}; + const u32 height {90000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2007_6353_cwe190_exiv2_exif_mul.cpp b/test/cve_corpus/cwe190/cve_2007_6353_cwe190_exiv2_exif_mul.cpp new file mode 100644 index 0000000..dc6692a --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2007_6353_cwe190_exiv2_exif_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2007-6353 +// cwe: CWE-190 +// product: Exiv2 (exif.cpp) +// version: Exiv2 library +// summary: Integer overflow in Exiv2 (exif.cpp). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=1500000000, element_size=3 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2007-6353 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: EXIF entry count times size overflows. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {1500000000U}; + const std::uint32_t element_size {3U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t bytes {static_cast(count * element_size)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 205032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {1500000000U}; + const u32 element_size {3U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2008_1374_cwe190_cups_pdftops_mul.cpp b/test/cve_corpus/cwe190/cve_2008_1374_cwe190_cups_pdftops_mul.cpp new file mode 100644 index 0000000..7ea215a --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2008_1374_cwe190_cups_pdftops_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2008-1374 +// cwe: CWE-190 +// product: CUPS pdftops filter (64-bit) +// version: Red Hat CUPS +// summary: Integer overflow in CUPS pdftops filter (64-bit). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=1073741900, element_size=4 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2008-1374 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Allocation size overflows on 64-bit in the pdftops filter. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {1073741900U}; + const std::uint32_t element_size {4U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t bytes {static_cast(count * element_size)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 304U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {1073741900U}; + const u32 element_size {4U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2008_2663_cwe190_ruby_ary_store_mul.cpp b/test/cve_corpus/cwe190/cve_2008_2663_cwe190_ruby_ary_store_mul.cpp new file mode 100644 index 0000000..840abb5 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2008_2663_cwe190_ruby_ary_store_mul.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2008-2663 +// cwe: CWE-190 +// product: Ruby (rb_ary_store) +// version: 1.8.x before the fixed patchlevels +// summary: Integer overflow in Ruby array storage sizing. +// root-cause: unsigned multiplication (capacity * element_size) for an array buffer +// root-cause-width: u32 +// trigger: capacity=600000000, element_size=8 +// consequence: undersized array buffer then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2008-2663 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: rb_ary_store grows an array by capacity * sizeof(VALUE) at u32 width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t capacity {600000000U}; + const std::uint32_t element_size {8U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(capacity, element_size)}; + const std::uint32_t bytes {static_cast(capacity * element_size)}; + + BOOST_TEST(true_bytes > static_cast(capacity)); + BOOST_TEST_EQ(bytes, 505032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 capacity {600000000U}; + const u32 element_size {8U}; + + BOOST_TEST_THROWS((void)(capacity * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(capacity, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2008_2826_cwe190_kernel_sctp_addrs_mul.cpp b/test/cve_corpus/cwe190/cve_2008_2826_cwe190_kernel_sctp_addrs_mul.cpp new file mode 100644 index 0000000..ce88025 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2008_2826_cwe190_kernel_sctp_addrs_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2008-2826 +// cwe: CWE-190 +// product: Linux kernel SCTP (getsockopt_local_addrs) +// version: before the 2008 fix +// summary: Integer overflow in Linux kernel SCTP (getsockopt_local_addrs). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=500000000, element_size=16 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2008-2826 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Address count times record size overflows. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {500000000U}; + const std::uint32_t element_size {16U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t bytes {static_cast(count * element_size)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 3705032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {500000000U}; + const u32 element_size {16U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2008_4019_cwe190_excel_rept_mul.cpp b/test/cve_corpus/cwe190/cve_2008_4019_cwe190_excel_rept_mul.cpp new file mode 100644 index 0000000..56d1288 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2008_4019_cwe190_excel_rept_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2008-4019 +// cwe: CWE-190 +// product: Microsoft Excel (REPT) +// version: Excel 2000 through 2007 +// summary: Integer overflow in Microsoft Excel (REPT). +// root-cause: unsigned multiplication of two values +// root-cause-width: u32 +// trigger: count=1000000, length=5000 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2008-4019 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: REPT repeats a string count times length, overflowing. +// notes: Modeled at the canonical multiplication overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {1000000U}; + const std::uint32_t length {5000U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(count, length)}; + const std::uint32_t bytes {static_cast(count * length)}; + + BOOST_TEST(true_bytes > static_cast(count)); + BOOST_TEST_EQ(bytes, 705032704U); + BOOST_TEST(static_cast(bytes) < true_bytes); +} + +void safe_reproduction() +{ + const u32 count {1000000U}; + const u32 length {5000U}; + + BOOST_TEST_THROWS((void)(count * length), std::overflow_error); + BOOST_TEST(!checked_mul(count, length).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2009_0723_cwe190_lcms_mul.cpp b/test/cve_corpus/cwe190/cve_2009_0723_cwe190_lcms_mul.cpp new file mode 100644 index 0000000..4794226 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2009_0723_cwe190_lcms_mul.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2009-0723 +// cwe: CWE-190 +// product: LittleCMS (lcms / liblcms) +// version: before 1.18beta2 +// summary: Integer overflow in a color transform table size allows code execution. +// root-cause: unsigned multiplication (entry_count * element_size) for a table allocation +// root-cause-width: u32 +// trigger: entry_count=2000000000, element_size=4 (product 8000000000 exceeds UINT32_MAX) +// consequence: undersized table allocation then heap buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2009-0723 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: lcms allocates transform tables sized entry_count * element_size at u32 width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t entry_count {2000000000U}; + const std::uint32_t element_size {4U}; + + const std::uint64_t true_bytes {cve_corpus::true_mul(entry_count, element_size)}; // 8000000000 + const std::uint32_t bytes {static_cast(entry_count * element_size)}; // wraps + + BOOST_TEST(true_bytes > static_cast(entry_count)); + BOOST_TEST_EQ(bytes, 3705032704U); // deterministic wrap + BOOST_TEST(static_cast(bytes) < true_bytes); // undersized +} + +void safe_reproduction() +{ + const u32 entry_count {2000000000U}; + const u32 element_size {4U}; + + BOOST_TEST_THROWS((void)(entry_count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(entry_count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2009_0946_cwe190_freetype_smooth_mul.cpp b/test/cve_corpus/cwe190/cve_2009_0946_cwe190_freetype_smooth_mul.cpp new file mode 100644 index 0000000..67ea1dc --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2009_0946_cwe190_freetype_smooth_mul.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2009-0946 +// cwe: CWE-190 +// product: FreeType (smooth rasterizer) +// version: 2.3.9 and earlier +// summary: Integer overflow from large font input values. +// root-cause: unsigned multiplication (width * rows) of glyph bitmap dimensions +// root-cause-width: u32 +// trigger: width=70000, rows=70000 +// consequence: undersized bitmap then code execution +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2009-0946 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: The smooth rasterizer sizes a glyph bitmap from width * rows at u32 width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {70000U}; + const std::uint32_t rows {70000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, rows)}; + const std::uint32_t pixels {static_cast(width * rows)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 605032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {70000U}; + const u32 rows {70000U}; + + BOOST_TEST_THROWS((void)(width * rows), std::overflow_error); + BOOST_TEST(!checked_mul(width, rows).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2010_3442_cwe190_kernel_alsa_mul.cpp b/test/cve_corpus/cwe190/cve_2010_3442_cwe190_kernel_alsa_mul.cpp new file mode 100644 index 0000000..c602a6b --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2010_3442_cwe190_kernel_alsa_mul.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2010-3442 +// cwe: CWE-190 +// product: Linux kernel ALSA (snd_ctl_new) +// version: before 2.6.36-rc5-next-20100929 +// summary: Integer overflow in ALSA control element allocation. +// root-cause: unsigned multiplication (count * element_size) for a control array +// root-cause-width: u32 +// trigger: count=1500000000, element_size=4 +// consequence: undersized allocation then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2010-3442 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: snd_ctl_new allocates count * element_size at u32 width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {1500000000U}; + const std::uint32_t element_size {4U}; + + const std::uint64_t true_total {cve_corpus::true_mul(count, element_size)}; + const std::uint32_t total {static_cast(count * element_size)}; + + BOOST_TEST(true_total > static_cast(count)); + BOOST_TEST_EQ(total, 1705032704U); + BOOST_TEST(static_cast(total) < true_total); +} + +void safe_reproduction() +{ + const u32 count {1500000000U}; + const u32 element_size {4U}; + + BOOST_TEST_THROWS((void)(count * element_size), std::overflow_error); + BOOST_TEST(!checked_mul(count, element_size).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2011_1178_cwe190_gimp_pcx_mul.cpp b/test/cve_corpus/cwe190/cve_2011_1178_cwe190_gimp_pcx_mul.cpp new file mode 100644 index 0000000..55dfa67 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2011_1178_cwe190_gimp_pcx_mul.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2011-1178 +// cwe: CWE-190 +// product: GIMP PCX plugin (load_image in file-pcx.c) +// version: 2.6.x and earlier +// summary: Integer overflow from PCX image dimensions. +// root-cause: unsigned multiplication (width * height) of PCX dimensions +// root-cause-width: u32 +// trigger: width=90000, height=90000 +// consequence: undersized bitmap then heap overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2011-1178 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: The PCX loader computes a pixel count from width * height at u32 width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {90000U}; + const std::uint32_t height {90000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; + const std::uint32_t pixels {static_cast(width * height)}; + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 3805032704U); + BOOST_TEST(static_cast(pixels) < true_pixels); +} + +void safe_reproduction() +{ + const u32 width {90000U}; + const u32 height {90000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2012_1185_cwe190_imagemagick_profile_add.cpp b/test/cve_corpus/cwe190/cve_2012_1185_cwe190_imagemagick_profile_add.cpp new file mode 100644 index 0000000..4b5a64b --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2012_1185_cwe190_imagemagick_profile_add.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2012-1185 +// cwe: CWE-190 +// product: ImageMagick (magick/profile.c) +// version: 6.7.5 and earlier +// summary: Integer overflow in profile length accumulation. +// root-cause: unsigned addition (existing_length + added_length) of profile sizes +// root-cause-width: u32 +// trigger: existing_length=3000000000, added_length=2000000000 +// consequence: memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2012-1185 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: Profile handling accumulates lengths by addition at u32 width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t existing_length {3000000000U}; + const std::uint32_t added_length {2000000000U}; + + const std::uint64_t true_total {cve_corpus::true_add(existing_length, added_length)}; + const std::uint32_t total {static_cast(existing_length + added_length)}; + + BOOST_TEST(true_total > static_cast(existing_length)); + BOOST_TEST_EQ(total, 705032704U); + BOOST_TEST(static_cast(total) < true_total); +} + +void safe_reproduction() +{ + const u32 existing_length {3000000000U}; + const u32 added_length {2000000000U}; + + BOOST_TEST_THROWS((void)(existing_length + added_length), std::overflow_error); + BOOST_TEST(!checked_add(existing_length, added_length).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2013_7437_cwe190_potrace_bmp_mul.cpp b/test/cve_corpus/cwe190/cve_2013_7437_cwe190_potrace_bmp_mul.cpp new file mode 100644 index 0000000..b366bb1 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2013_7437_cwe190_potrace_bmp_mul.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2013-7437 +// cwe: CWE-190 +// product: potrace +// version: 1.11 +// summary: Integer overflow from large BMP dimensions triggers a buffer overflow. +// root-cause: unsigned multiplication (width * height) of BMP image dimensions +// root-cause-width: u32 +// trigger: width=100000, height=100000 (product 10000000000 exceeds UINT32_MAX) +// consequence: undersized bitmap allocation then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2013-7437 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: The BMP reader computes a pixel count from width * height at u32 width. +// notes: Modeled with representative dimensions whose product wraps below the true size. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t width {100000U}; + const std::uint32_t height {100000U}; + + const std::uint64_t true_pixels {cve_corpus::true_mul(width, height)}; // 10000000000 + const std::uint32_t pixels {static_cast(width * height)}; // wraps to 1410065408 + + BOOST_TEST(true_pixels > static_cast(width)); + BOOST_TEST_EQ(pixels, 1410065408U); // deterministic wrap + BOOST_TEST(static_cast(pixels) < true_pixels); // undersized +} + +void safe_reproduction() +{ + const u32 width {100000U}; + const u32 height {100000U}; + + BOOST_TEST_THROWS((void)(width * height), std::overflow_error); + BOOST_TEST(!checked_mul(width, height).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2014_4608_cwe190_kernel_lzo_add.cpp b/test/cve_corpus/cwe190/cve_2014_4608_cwe190_kernel_lzo_add.cpp new file mode 100644 index 0000000..b6008f7 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2014_4608_cwe190_kernel_lzo_add.cpp @@ -0,0 +1,81 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2014-4608 +// cwe: CWE-190 +// product: Linux kernel LZO decompressor (lzo1x_decompress_safe) +// version: before 3.15.2 +// summary: Integer overflow in the LZO decompressor length arithmetic causes memory corruption. +// root-cause: unsigned addition (output_position + run_length) overflows the 32-bit accumulator +// root-cause-width: u32 +// trigger: output_position=4000000000, run_length=1000000000 (sum exceeds UINT32_MAX) +// consequence: wrapped length bypasses the safe-decompress bound then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2014-4608 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: A crafted stream drives a length accumulation past UINT32_MAX; modeled as +// notes: u32 addition of a position and a run length. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include "../cve_corpus_util.hpp" + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t output_position {4000000000U}; + const std::uint32_t run_length {1000000000U}; + + const std::uint64_t true_end {cve_corpus::true_add(output_position, run_length)}; // 5000000000 + const std::uint32_t end {static_cast(output_position + run_length)}; // wraps + + BOOST_TEST(true_end > static_cast(output_position)); + BOOST_TEST_EQ(end, 705032704U); // deterministic wrap + BOOST_TEST(static_cast(end) < true_end); // apparent end before real end +} + +void safe_reproduction() +{ + const u32 output_position {4000000000U}; + const u32 run_length {1000000000U}; + + BOOST_TEST_THROWS((void)(output_position + run_length), std::overflow_error); + BOOST_TEST(!checked_add(output_position, run_length).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2015_1283_cwe190_expat_getbuffer_add.cpp b/test/cve_corpus/cwe190/cve_2015_1283_cwe190_expat_getbuffer_add.cpp new file mode 100644 index 0000000..d7f0726 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2015_1283_cwe190_expat_getbuffer_add.cpp @@ -0,0 +1,90 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-1283 +// cwe: CWE-190 +// product: Expat (libexpat) +// version: through 2.1.0 +// summary: Integer overflow in XML_GetBuffer buffer size computation allows heap corruption. +// root-cause: signed addition (len + keep) of two int buffer sizes overflows INT_MAX +// root-cause-width: i32 +// trigger: len=2000000000, keep=2000000000 (sum 4000000000 exceeds INT_MAX) +// consequence: negative/undersized buffer size then heap buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-1283 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: XML_GetBuffer computed neededSize = len + keep as int; the fix added +// notes: the check len > INT_MAX - keep. Modeled as i32 signed addition; the +// notes: native wrap is shown via the well defined unsigned round trip (no UB). +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include +#include + +using namespace boost::safe_numbers; + +// Native signed addition overflows INT_MAX and wraps to a negative value, which is +// then used as an allocation size. +void native_reproduction() +{ + const std::int32_t len {2000000000}; + const std::int32_t keep {2000000000}; + + // Ground truth in a wider signed type: 4000000000 > INT32_MAX. + const std::int64_t true_size {static_cast(len) + static_cast(keep)}; + + // The vulnerable 32-bit computation, shown via the well defined two's complement + // round trip so this reproduction itself performs no signed overflow (no UB). + const std::int32_t needed {static_cast( + static_cast(len) + static_cast(keep))}; + + BOOST_TEST(true_size > static_cast(std::numeric_limits::max())); + BOOST_TEST(needed < 0); // wraps negative + BOOST_TEST(static_cast(needed) != true_size); // silently wrong value +} + +// The identical addition in safe types throws before the wrong size is produced. +void safe_reproduction() +{ + const i32 len {2000000000}; + const i32 keep {2000000000}; + + BOOST_TEST_THROWS((void)(len + keep), std::overflow_error); + BOOST_TEST(!checked_add(len, keep).has_value()); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe190/cve_2018_13785_cwe190_libpng_width_bounded.cpp b/test/cve_corpus/cwe190/cve_2018_13785_cwe190_libpng_width_bounded.cpp new file mode 100644 index 0000000..66cdf96 --- /dev/null +++ b/test/cve_corpus/cwe190/cve_2018_13785_cwe190_libpng_width_bounded.cpp @@ -0,0 +1,74 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-13785 +// cwe: CWE-190, CWE-369 +// product: libpng +// version: 1.6.34 +// summary: Wrong row_factor calculation in png_check_chunk_length overflows, then divides by zero. +// root-cause: an oversized image width is used without enforcing the documented width limit +// root-cause-width: u32 +// trigger: width=2147483648 (2^31), far above the PNG user width limit +// consequence: integer overflow and resultant divide by zero +// classification: PREVENTED_BOUNDED +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-13785 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: NVD tags this CVE both CWE-190 and CWE-369; it is counted under CWE-190. +// notes: libpng documents a user width limit (default 1000000). Expressing that +// notes: domain as bounded_uint rejects the oversized width at construction, before +// notes: any row_factor arithmetic runs. The width is a runtime value, so the check +// notes: fires at runtime rather than at compile time. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +// The documented legal domain of a PNG width, per libpng's default user limit. +using png_width = bounded_uint<1U, 1000000U>; + +// Native code applies no domain check on the width; the oversized value flows into +// the row_factor arithmetic and misbehaves. +void native_reproduction() +{ + const std::uint32_t max_legal_width {1000000U}; + std::uint32_t attacker_width {2147483648U}; // 2^31, a runtime (non constant) value + + BOOST_TEST(attacker_width > max_legal_width); // precondition violated, unchecked natively +} + +// The precondition lives in the type; the out of domain width is rejected at the +// boundary, before it can reach the overflow or the divide. +void safe_reproduction() +{ + std::uint32_t attacker_width {2147483648U}; + BOOST_TEST_THROWS((png_width{u32{attacker_width}}), std::domain_error); + + std::uint32_t legal_width {800U}; + BOOST_TEST_NO_THROW((void)png_width{u32{legal_width}}); // a width within the domain is accepted +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2004_0184_cwe191_tcpdump_isakmp_underflow.cpp b/test/cve_corpus/cwe191/cve_2004_0184_cwe191_tcpdump_isakmp_underflow.cpp new file mode 100644 index 0000000..5736d26 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2004_0184_cwe191_tcpdump_isakmp_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2004-0184 +// cwe: CWE-191 +// product: tcpdump (isakmp_id_print) +// version: 3.8.1 and earlier +// summary: Integer underflow in ISAKMP identification printing causes a crash. +// root-cause: unsigned subtraction (item_len - fixed_header) with item_len too small +// root-cause-width: u32 +// trigger: item_len=2, fixed_header=4 +// consequence: wrapped length drives an out of bounds read and crash +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2004-0184 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: A short ISAKMP item length is reduced by a fixed header size. Modeled at u32. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t item_len {2U}; // attacker supplied, too small + const std::uint32_t fixed_header {4U}; + const std::uint32_t payload {item_len - fixed_header}; // well defined unsigned wrap + + BOOST_TEST_EQ(payload, 4294967294U); // wraps near UINT32_MAX + BOOST_TEST(payload > item_len); +} + +void safe_reproduction() +{ + const u32 item_len {2U}; + const u32 fixed_header {4U}; + + BOOST_TEST_THROWS((void)(item_len - fixed_header), std::underflow_error); + BOOST_TEST(!checked_sub(item_len, fixed_header).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2004_0816_cwe191_iptables_underflow.cpp b/test/cve_corpus/cwe191/cve_2004_0816_cwe191_iptables_underflow.cpp new file mode 100644 index 0000000..c0a6172 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2004_0816_cwe191_iptables_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2004-0816 +// cwe: CWE-191 +// product: Linux iptables firewall logging +// version: before 2.6.8 +// summary: Integer underflow in Linux iptables firewall logging. +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=8, requested=20 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2004-0816 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {8U}; + const std::uint32_t requested {20U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967284U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {8U}; + const u32 requested {20U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2004_1002_cwe191_pppd_cbcp_underflow.cpp b/test/cve_corpus/cwe191/cve_2004_1002_cwe191_pppd_cbcp_underflow.cpp new file mode 100644 index 0000000..2dbaa75 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2004_1002_cwe191_pppd_cbcp_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2004-1002 +// cwe: CWE-191 +// product: pppd (cbcp.c in ppp) +// version: 2.4.1 +// summary: Integer underflow from an invalid CBCP packet length. +// root-cause: unsigned subtraction (packet_length - fixed_header) +// root-cause-width: u32 +// trigger: packet_length=3, fixed_header=6 +// consequence: crash from an out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2004-1002 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: A short CBCP length is decremented by a fixed header size. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t packet_length {3U}; + const std::uint32_t fixed_header {6U}; + const std::uint32_t remaining {packet_length - fixed_header}; + + BOOST_TEST_EQ(remaining, 4294967293U); + BOOST_TEST(remaining > packet_length); +} + +void safe_reproduction() +{ + const u32 packet_length {3U}; + const u32 fixed_header {6U}; + + BOOST_TEST_THROWS((void)(packet_length - fixed_header), std::underflow_error); + BOOST_TEST(!checked_sub(packet_length, fixed_header).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2005_0199_cwe191_ngircd_mask_underflow.cpp b/test/cve_corpus/cwe191/cve_2005_0199_cwe191_ngircd_mask_underflow.cpp new file mode 100644 index 0000000..137f5af --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2005_0199_cwe191_ngircd_mask_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2005-0199 +// cwe: CWE-191 +// product: ngIRCd (Lists_MakeMask in lists.c) +// version: before 0.8.2 +// summary: Integer underflow in mask list handling. +// root-cause: unsigned subtraction (length - offset) with length too small +// root-cause-width: u32 +// trigger: length=1, offset=3 +// consequence: crash from an out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2005-0199 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Lists_MakeMask subtracts an offset from a short length. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t length {1U}; + const std::uint32_t offset {3U}; + const std::uint32_t remaining {length - offset}; + + BOOST_TEST_EQ(remaining, 4294967294U); + BOOST_TEST(remaining > length); +} + +void safe_reproduction() +{ + const u32 length {1U}; + const u32 offset {3U}; + + BOOST_TEST_THROWS((void)(length - offset), std::underflow_error); + BOOST_TEST(!checked_sub(length, offset).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2009_3301_cwe191_ooo_ww8_underflow.cpp b/test/cve_corpus/cwe191/cve_2009_3301_cwe191_ooo_ww8_underflow.cpp new file mode 100644 index 0000000..33c13aa --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2009_3301_cwe191_ooo_ww8_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2009-3301 +// cwe: CWE-191 +// product: OpenOffice.org (ww8par2.cxx) +// version: before 3.2 +// summary: Integer underflow in OpenOffice.org (ww8par2.cxx). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=4, requested=16 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2009-3301 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {4U}; + const std::uint32_t requested {16U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967284U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {4U}; + const u32 requested {16U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2010_2497_cwe191_freetype_glyph_underflow.cpp b/test/cve_corpus/cwe191/cve_2010_2497_cwe191_freetype_glyph_underflow.cpp new file mode 100644 index 0000000..7d5082d --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2010_2497_cwe191_freetype_glyph_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2010-2497 +// cwe: CWE-191 +// product: FreeType (glyph handling) +// version: before 2.4.0 +// summary: Integer underflow in glyph handling. +// root-cause: unsigned subtraction (count - consumed) with count too small +// root-cause-width: u32 +// trigger: count=3, consumed=10 +// consequence: crash or code execution +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2010-2497 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Glyph handling subtracts a consumed count from a smaller total. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t count {3U}; + const std::uint32_t consumed {10U}; + const std::uint32_t remaining {count - consumed}; + + BOOST_TEST_EQ(remaining, 4294967289U); + BOOST_TEST(remaining > count); +} + +void safe_reproduction() +{ + const u32 count {3U}; + const u32 consumed {10U}; + + BOOST_TEST_THROWS((void)(count - consumed), std::underflow_error); + BOOST_TEST(!checked_sub(count, consumed).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2010_4164_cwe191_kernel_x25_underflow.cpp b/test/cve_corpus/cwe191/cve_2010_4164_cwe191_kernel_x25_underflow.cpp new file mode 100644 index 0000000..029c861 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2010_4164_cwe191_kernel_x25_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2010-4164 +// cwe: CWE-191 +// product: Linux kernel X.25 (x25_parse_facilities) +// version: before 2.6.36.2 +// summary: Integer underflow in Linux kernel X.25 (x25_parse_facilities). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=2, requested=10 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2010-4164 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {2U}; + const std::uint32_t requested {10U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967288U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {2U}; + const u32 requested {10U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2010_4529_cwe191_kernel_irda_underflow.cpp b/test/cve_corpus/cwe191/cve_2010_4529_cwe191_kernel_irda_underflow.cpp new file mode 100644 index 0000000..10bd7f9 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2010_4529_cwe191_kernel_irda_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2010-4529 +// cwe: CWE-191 +// product: Linux kernel IrDA (irda_getsockopt) +// version: before 2.6.37 +// summary: Integer underflow in Linux kernel IrDA (irda_getsockopt). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=1, requested=4 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2010-4529 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {1U}; + const std::uint32_t requested {4U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967293U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {1U}; + const u32 requested {4U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2011_1770_cwe191_kernel_dccp_underflow.cpp b/test/cve_corpus/cwe191/cve_2011_1770_cwe191_kernel_dccp_underflow.cpp new file mode 100644 index 0000000..0fee0c2 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2011_1770_cwe191_kernel_dccp_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2011-1770 +// cwe: CWE-191 +// product: Linux kernel DCCP (dccp_parse_options) +// version: before 2.6.33.14 +// summary: Integer underflow in DCCP option parsing. +// root-cause: unsigned subtraction (option_length - fixed) with option_length too small +// root-cause-width: u32 +// trigger: option_length=2, fixed=12 +// consequence: remote denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2011-1770 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: dccp_parse_options reduces a short option length by a fixed amount. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t option_length {2U}; + const std::uint32_t fixed {12U}; + const std::uint32_t remaining {option_length - fixed}; + + BOOST_TEST_EQ(remaining, 4294967286U); + BOOST_TEST(remaining > option_length); +} + +void safe_reproduction() +{ + const u32 option_length {2U}; + const u32 fixed {12U}; + + BOOST_TEST_THROWS((void)(option_length - fixed), std::underflow_error); + BOOST_TEST(!checked_sub(option_length, fixed).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2011_2497_cwe191_kernel_l2cap_underflow.cpp b/test/cve_corpus/cwe191/cve_2011_2497_cwe191_kernel_l2cap_underflow.cpp new file mode 100644 index 0000000..fe240af --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2011_2497_cwe191_kernel_l2cap_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2011-2497 +// cwe: CWE-191 +// product: Linux kernel Bluetooth L2CAP (l2cap_config_req) +// version: before 3.0 +// summary: Integer underflow in L2CAP config handling allows remote denial of service or worse. +// root-cause: unsigned subtraction (command_len - option_header) with command_len too small +// root-cause-width: u32 +// trigger: command_len=4, option_header=8 +// consequence: wrapped remaining length drives an over read or over write +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2011-2497 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: A short command length is decremented by a fixed option header size. Modeled at u32. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t command_len {4U}; // attacker supplied, too small + const std::uint32_t option_header {8U}; + const std::uint32_t remaining {command_len - option_header}; // well defined unsigned wrap + + BOOST_TEST_EQ(remaining, 4294967292U); // wraps near UINT32_MAX + BOOST_TEST(remaining > command_len); // apparent remaining exceeds the packet +} + +void safe_reproduction() +{ + const u32 command_len {4U}; + const u32 option_header {8U}; + + BOOST_TEST_THROWS((void)(command_len - option_header), std::underflow_error); + BOOST_TEST(!checked_sub(command_len, option_header).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2011_4031_cwe191_ffmpeg_asfrtp_underflow.cpp b/test/cve_corpus/cwe191/cve_2011_4031_cwe191_ffmpeg_asfrtp_underflow.cpp new file mode 100644 index 0000000..c56fbd1 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2011_4031_cwe191_ffmpeg_asfrtp_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2011-4031 +// cwe: CWE-191 +// product: FFmpeg (asfrtp_parse_packet) +// version: before 0.8.3 +// summary: Integer underflow in ASF RTP depacketization allows code execution. +// root-cause: unsigned subtraction (packet_size - header) with packet_size too small +// root-cause-width: u32 +// trigger: packet_size=4, header=20 +// consequence: code execution +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2011-4031 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: asfrtp_parse_packet subtracts a header size from a short packet size. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t packet_size {4U}; + const std::uint32_t header {20U}; + const std::uint32_t remaining {packet_size - header}; + + BOOST_TEST_EQ(remaining, 4294967280U); + BOOST_TEST(remaining > packet_size); +} + +void safe_reproduction() +{ + const u32 packet_size {4U}; + const u32 header {20U}; + + BOOST_TEST_THROWS((void)(packet_size - header), std::underflow_error); + BOOST_TEST(!checked_sub(packet_size, header).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2013_6424_cwe191_xorg_trapezoid_underflow.cpp b/test/cve_corpus/cwe191/cve_2013_6424_cwe191_xorg_trapezoid_underflow.cpp new file mode 100644 index 0000000..f28b358 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2013_6424_cwe191_xorg_trapezoid_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2013-6424 +// cwe: CWE-191 +// product: X.Org (xTrapezoidValid in render/picture.h) +// version: X.Org server +// summary: Integer underflow in the xTrapezoidValid macro. +// root-cause: unsigned subtraction (bottom - top) with bottom less than top +// root-cause-width: u32 +// trigger: bottom=7, top=15 +// consequence: crash from an out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2013-6424 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: xTrapezoidValid computes bottom - top; a reversed pair wraps. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t bottom {7U}; + const std::uint32_t top {15U}; + const std::uint32_t remaining {bottom - top}; + + BOOST_TEST_EQ(remaining, 4294967288U); + BOOST_TEST(remaining > bottom); +} + +void safe_reproduction() +{ + const u32 bottom {7U}; + const u32 top {15U}; + + BOOST_TEST_THROWS((void)(bottom - top), std::underflow_error); + BOOST_TEST(!checked_sub(bottom, top).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2013_6425_cwe191_pixman_trapezoid_underflow.cpp b/test/cve_corpus/cwe191/cve_2013_6425_cwe191_pixman_trapezoid_underflow.cpp new file mode 100644 index 0000000..f04c51a --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2013_6425_cwe191_pixman_trapezoid_underflow.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2013-6425 +// cwe: CWE-191 +// product: Pixman (as used in X.Org server and cairo) +// version: before 0.32.0 +// summary: Integer underflow in the pixman_trapezoid_valid macro allows denial of service. +// root-cause: unsigned subtraction (bottom - top) with bottom less than top +// root-cause-width: u32 +// trigger: bottom=5, top=10 +// consequence: wrapped height drives an out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2013-6425 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: The trapezoid validity check computes bottom - top; a reversed pair wraps. Modeled at u32. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t bottom {5U}; // attacker supplied, reversed pair + const std::uint32_t top {10U}; + const std::uint32_t height {bottom - top}; // well defined unsigned wrap + + BOOST_TEST_EQ(height, 4294967291U); // wraps near UINT32_MAX + BOOST_TEST(height > bottom); +} + +void safe_reproduction() +{ + const u32 bottom {5U}; + const u32 top {10U}; + + BOOST_TEST_THROWS((void)(bottom - top), std::underflow_error); + BOOST_TEST(!checked_sub(bottom, top).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2014_0497_cwe191_flash_underflow.cpp b/test/cve_corpus/cwe191/cve_2014_0497_cwe191_flash_underflow.cpp new file mode 100644 index 0000000..4fdbdd7 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2014_0497_cwe191_flash_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2014-0497 +// cwe: CWE-191 +// product: Adobe Flash Player +// version: before 11.7.700.261 +// summary: Integer underflow in Adobe Flash Player. +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=6, requested=32 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2014-0497 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {6U}; + const std::uint32_t requested {32U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967270U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {6U}; + const u32 requested {32U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2014_8768_cwe191_tcpdump_geonet_underflow.cpp b/test/cve_corpus/cwe191/cve_2014_8768_cwe191_tcpdump_geonet_underflow.cpp new file mode 100644 index 0000000..8b169f3 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2014_8768_cwe191_tcpdump_geonet_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2014-8768 +// cwe: CWE-191 +// product: tcpdump (geonet_print) +// version: 4.5.0 through 4.6.2 +// summary: Integer underflow in tcpdump (geonet_print). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=3, requested=8 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2014-8768 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {3U}; + const std::uint32_t requested {8U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967291U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {3U}; + const u32 requested {8U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2014_9087_cwe191_libksba_oid_underflow.cpp b/test/cve_corpus/cwe191/cve_2014_9087_cwe191_libksba_oid_underflow.cpp new file mode 100644 index 0000000..f0b7462 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2014_9087_cwe191_libksba_oid_underflow.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2014-9087 +// cwe: CWE-191 +// product: Libksba (as used in GnuPG) +// version: before 1.3.2 +// summary: Integer underflow in ksba_oid_to_str from a zero length OID triggers a buffer overflow. +// root-cause: unsigned subtraction (length - 1) with length zero wraps to a huge value +// root-cause-width: u32 +// trigger: length=0, then length - 1 +// consequence: oversized length drives an out of bounds write +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2014-9087 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: A zero length field flows into a length - 1 computation. Modeled at u32 width; +// notes: the wrap yields UINT32_MAX. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t length {0U}; // attacker supplied zero length + const std::uint32_t n {length - 1U}; // well defined unsigned wrap + + BOOST_TEST_EQ(n, 4294967295U); // wraps to UINT32_MAX + BOOST_TEST(n > length); // apparent size far exceeds the real length +} + +void safe_reproduction() +{ + const u32 length {0U}; + + BOOST_TEST_THROWS((void)(length - u32{1U}), std::underflow_error); + BOOST_TEST(!checked_sub(length, u32{1U}).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2015_0537_cwe191_rsa_bsafe_underflow.cpp b/test/cve_corpus/cwe191/cve_2015_0537_cwe191_rsa_bsafe_underflow.cpp new file mode 100644 index 0000000..ac9e8f1 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2015_0537_cwe191_rsa_bsafe_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-0537 +// cwe: CWE-191 +// product: EMC RSA BSAFE (base64 decode) +// version: Micro Edition Suite +// summary: Integer underflow in EMC RSA BSAFE (base64 decode). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=2, requested=5 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-0537 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {2U}; + const std::uint32_t requested {5U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967293U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {2U}; + const u32 requested {5U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2015_1208_cwe191_ffmpeg_mov_underflow.cpp b/test/cve_corpus/cwe191/cve_2015_1208_cwe191_ffmpeg_mov_underflow.cpp new file mode 100644 index 0000000..61aa060 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2015_1208_cwe191_ffmpeg_mov_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-1208 +// cwe: CWE-191 +// product: FFmpeg (mov_read_default) +// version: before 2.4.6 +// summary: Integer underflow in FFmpeg (mov_read_default). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=9, requested=40 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-1208 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {9U}; + const std::uint32_t requested {40U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967265U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {9U}; + const u32 requested {40U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2015_2311_cwe191_capnproto_underflow.cpp b/test/cve_corpus/cwe191/cve_2015_2311_cwe191_capnproto_underflow.cpp new file mode 100644 index 0000000..3940509 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2015_2311_cwe191_capnproto_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-2311 +// cwe: CWE-191 +// product: Cap'n Proto +// version: before 0.4.1.1 +// summary: Integer underflow in Cap'n Proto. +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=2, requested=17 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-2311 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {2U}; + const std::uint32_t requested {17U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967281U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {2U}; + const u32 requested {17U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2015_5212_cwe191_libreoffice_underflow.cpp b/test/cve_corpus/cwe191/cve_2015_5212_cwe191_libreoffice_underflow.cpp new file mode 100644 index 0000000..9e236f6 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2015_5212_cwe191_libreoffice_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-5212 +// cwe: CWE-191 +// product: LibreOffice / Apache OpenOffice +// version: LibreOffice before 4.4.5 +// summary: Integer underflow in LibreOffice / Apache OpenOffice. +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=10, requested=40 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-5212 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {10U}; + const std::uint32_t requested {40U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967266U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {10U}; + const u32 requested {40U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2016_10166_cwe191_libgd_interp_underflow.cpp b/test/cve_corpus/cwe191/cve_2016_10166_cwe191_libgd_interp_underflow.cpp new file mode 100644 index 0000000..645a4ce --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2016_10166_cwe191_libgd_interp_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-10166 +// cwe: CWE-191 +// product: GD Graphics Library (gd_interpolation.c) +// version: libgd +// summary: Integer underflow in GD Graphics Library (gd_interpolation.c). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=1, requested=9 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-10166 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {1U}; + const std::uint32_t requested {9U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967288U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {1U}; + const u32 requested {9U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2016_10268_cwe191_libtiff_tiffcp_underflow.cpp b/test/cve_corpus/cwe191/cve_2016_10268_cwe191_libtiff_tiffcp_underflow.cpp new file mode 100644 index 0000000..bbc87c1 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2016_10268_cwe191_libtiff_tiffcp_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-10268 +// cwe: CWE-191 +// product: LibTIFF (tools/tiffcp.c) +// version: 4.0.7 +// summary: Integer underflow in LibTIFF (tools/tiffcp.c). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=7, requested=15 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-10268 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {7U}; + const std::uint32_t requested {15U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967288U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {7U}; + const u32 requested {15U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2016_1925_cwe191_lha_header_underflow.cpp b/test/cve_corpus/cwe191/cve_2016_1925_cwe191_lha_header_underflow.cpp new file mode 100644 index 0000000..607bede --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2016_1925_cwe191_lha_header_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-1925 +// cwe: CWE-191 +// product: lha (header.c) +// version: lha +// summary: Integer underflow in lha (header.c). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=5, requested=21 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-1925 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {5U}; + const std::uint32_t requested {21U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967280U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {5U}; + const u32 requested {21U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2016_7800_cwe191_graphicsmagick_meta_underflow.cpp b/test/cve_corpus/cwe191/cve_2016_7800_cwe191_graphicsmagick_meta_underflow.cpp new file mode 100644 index 0000000..81cb21d --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2016_7800_cwe191_graphicsmagick_meta_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-7800 +// cwe: CWE-191 +// product: GraphicsMagick (coders/meta.c) +// version: 1.3.25 and earlier +// summary: Integer underflow in GraphicsMagick (coders/meta.c). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=4, requested=12 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-7800 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {4U}; + const std::uint32_t requested {12U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967288U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {4U}; + const u32 requested {12U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2017_14496_cwe191_dnsmasq_underflow.cpp b/test/cve_corpus/cwe191/cve_2017_14496_cwe191_dnsmasq_underflow.cpp new file mode 100644 index 0000000..599293d --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2017_14496_cwe191_dnsmasq_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-14496 +// cwe: CWE-191 +// product: dnsmasq (add_pseudoheader) +// version: before 2.78 +// summary: Integer underflow in dnsmasq (add_pseudoheader). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=6, requested=30 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-14496 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {6U}; + const std::uint32_t requested {30U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967272U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {6U}; + const u32 requested {30U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2017_15874_cwe191_busybox_unlzma_underflow.cpp b/test/cve_corpus/cwe191/cve_2017_15874_cwe191_busybox_unlzma_underflow.cpp new file mode 100644 index 0000000..bf812f7 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2017_15874_cwe191_busybox_unlzma_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-15874 +// cwe: CWE-191 +// product: BusyBox (decompress_unlzma.c) +// version: 1.27.2 +// summary: Integer underflow in BusyBox (decompress_unlzma.c). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=1, requested=13 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-15874 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {1U}; + const std::uint32_t requested {13U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967284U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {1U}; + const u32 requested {13U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2017_6313_cwe191_gdkpixbuf_icns_underflow.cpp b/test/cve_corpus/cwe191/cve_2017_6313_cwe191_gdkpixbuf_icns_underflow.cpp new file mode 100644 index 0000000..f131670 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2017_6313_cwe191_gdkpixbuf_icns_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-6313 +// cwe: CWE-191 +// product: gdk-pixbuf (io-icns.c) +// version: gdk-pixbuf +// summary: Integer underflow in gdk-pixbuf (io-icns.c). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=8, requested=40 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-6313 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {8U}; + const std::uint32_t requested {40U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967264U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {8U}; + const u32 requested {40U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2017_8911_cwe191_tnef_underflow.cpp b/test/cve_corpus/cwe191/cve_2017_8911_cwe191_tnef_underflow.cpp new file mode 100644 index 0000000..b3687f1 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2017_8911_cwe191_tnef_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-8911 +// cwe: CWE-191 +// product: tnef (unicode_to_utf8) +// version: 1.4.14 +// summary: Integer underflow in tnef (unicode_to_utf8). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=3, requested=11 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-8911 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {3U}; + const std::uint32_t requested {11U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967288U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {3U}; + const u32 requested {11U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2017_8924_cwe191_kernel_io_ti_underflow.cpp b/test/cve_corpus/cwe191/cve_2017_8924_cwe191_kernel_io_ti_underflow.cpp new file mode 100644 index 0000000..2ce796c --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2017_8924_cwe191_kernel_io_ti_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-8924 +// cwe: CWE-191 +// product: Linux kernel USB serial (io_ti.c) +// version: before 4.10.4 +// summary: Integer underflow in Linux kernel USB serial (io_ti.c). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=2, requested=6 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-8924 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {2U}; + const std::uint32_t requested {6U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967292U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {2U}; + const u32 requested {6U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe191/cve_2017_9214_cwe191_openvswitch_underflow.cpp b/test/cve_corpus/cwe191/cve_2017_9214_cwe191_openvswitch_underflow.cpp new file mode 100644 index 0000000..54f3ea0 --- /dev/null +++ b/test/cve_corpus/cwe191/cve_2017_9214_cwe191_openvswitch_underflow.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-9214 +// cwe: CWE-191 +// product: Open vSwitch (queue config reply) +// version: OvS 2.7.0 +// summary: Integer underflow in Open vSwitch (queue config reply). +// root-cause: unsigned subtraction with the minuend too small +// root-cause-width: u32 +// trigger: available=4, requested=24 +// consequence: wrapped length then out of bounds access +// classification: PREVENTED_RUNTIME +// expected-exception: std::underflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-9214 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-191&resultsPerPage=200&startIndex=0 +// notes: Unsigned length subtraction wraps below zero. +// notes: Modeled at the canonical subtraction underflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t available {4U}; + const std::uint32_t requested {24U}; + const std::uint32_t remaining {available - requested}; + + BOOST_TEST_EQ(remaining, 4294967276U); + BOOST_TEST(remaining > available); +} + +void safe_reproduction() +{ + const u32 available {4U}; + const u32 requested {24U}; + + BOOST_TEST_THROWS((void)(available - requested), std::underflow_error); + BOOST_TEST(!checked_sub(available, requested).has_value()); +} + +void bounded_reproduction() +{ + // A length required to be at least a header size is declared with a minimum + // bound; a too small length is rejected before the subtraction underflows. + using bounded_length = bounded_uint<8u, 1000000u>; + std::uint32_t attacker_length {4U}; + BOOST_TEST_THROWS((bounded_length{u32{attacker_length}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_length{u32{64U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2004_0804_cwe369_libtiff_dirread_divzero.cpp b/test/cve_corpus/cwe369/cve_2004_0804_cwe369_libtiff_dirread_divzero.cpp new file mode 100644 index 0000000..a7ba841 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2004_0804_cwe369_libtiff_dirread_divzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2004-0804 +// cwe: CWE-369 +// product: LibTIFF (tif_dirread.c) +// version: see advisory +// summary: Divide by zero in TIFF directory reading crashes the reader. +// root-cause: division (value / field) with an attacker controlled zero field +// root-cause-width: u32 +// trigger: value=8, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2004-0804 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted TIFF drives a zero divisor into tif_dirread arithmetic. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {8U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {8U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2009_1887_cwe369_netsnmp_divzero.cpp b/test/cve_corpus/cwe369/cve_2009_1887_cwe369_netsnmp_divzero.cpp new file mode 100644 index 0000000..ffac47a --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2009_1887_cwe369_netsnmp_divzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2009-1887 +// cwe: CWE-369 +// product: net-snmp (snmp_agent.c) +// version: 5.0.9 (RHEL 3) +// summary: Divide by zero in snmpd crashes the daemon. +// root-cause: division (value / step) with an attacker controlled zero step +// root-cause-width: u32 +// trigger: value=100, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2009-1887 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted request drives a zero divisor into agent arithmetic. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {100U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {100U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2011_1012_cwe369_kernel_ldm_modzero.cpp b/test/cve_corpus/cwe369/cve_2011_1012_cwe369_kernel_ldm_modzero.cpp new file mode 100644 index 0000000..5d3f5e5 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2011_1012_cwe369_kernel_ldm_modzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2011-1012 +// cwe: CWE-369 +// product: Linux kernel LDM (ldm_parse_vmdb) +// version: before 2.6.38-rc6-git6 +// summary: Divide by zero from an unvalidated VBLK size in an LDM partition. +// root-cause: modulo (offset % vblk_size) with a zero vblk_size +// root-cause-width: u32 +// trigger: offset=512, divisor=0 +// consequence: divide by zero (SIGFPE) kernel crash +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2011-1012 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: ldm_parse_vmdb does not validate the VBLK size before using it as a divisor. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t offset {512U}; + const std::uint32_t vblk_size {0U}; + + BOOST_TEST_EQ(vblk_size, 0U); + BOOST_TEST(offset > 0U); +} + +void safe_reproduction() +{ + const u32 offset {512U}; + const u32 vblk_size {0U}; + + BOOST_TEST_THROWS((void)(offset % vblk_size), std::domain_error); + BOOST_TEST(!checked_mod(offset, vblk_size).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2012_0207_cwe369_kernel_igmp_modzero.cpp b/test/cve_corpus/cwe369/cve_2012_0207_cwe369_kernel_igmp_modzero.cpp new file mode 100644 index 0000000..b1b7b86 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2012_0207_cwe369_kernel_igmp_modzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2012-0207 +// cwe: CWE-369 +// product: Linux kernel IPv4 IGMP (igmp_heard_query) +// version: before 3.2.1 +// summary: Divide by zero in IGMP query handling allows remote denial of service. +// root-cause: modulo (value % divisor) where a crafted query yields a zero divisor +// root-cause-width: u32 +// trigger: value=1000, divisor=0 +// consequence: divide by zero (SIGFPE) kernel denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2012-0207 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted IGMPv3 query drives a zero divisor into a modulo. Modeled at u32. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {1000U}; + const std::uint32_t divisor {0U}; // attacker controlled + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {1000U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value % divisor), std::domain_error); + BOOST_TEST(!checked_mod(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2014_9756_cwe369_libsndfile_divzero.cpp b/test/cve_corpus/cwe369/cve_2014_9756_cwe369_libsndfile_divzero.cpp new file mode 100644 index 0000000..61323b9 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2014_9756_cwe369_libsndfile_divzero.cpp @@ -0,0 +1,80 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2014-9756 +// cwe: CWE-369 +// product: libsndfile (psf_fwrite) +// version: through 1.0.25 +// summary: Divide by zero in psf_fwrite from a zero item size crashes the application. +// root-cause: division (bytes_to_write / item_size) with an attacker controlled zero item size +// root-cause-width: u32 +// trigger: bytes_to_write=4096, item_size=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2014-9756 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: Native divides without guarding the zero divisor, which traps. The native arm +// notes: documents the trigger; it does not perform the trapping division. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +// Native code divides bytes_to_write by item_size with no guard. The division is +// omitted here because dividing by zero is undefined and would trap; the trigger +// condition is asserted instead. +void native_reproduction() +{ + const std::uint32_t bytes_to_write {4096U}; + const std::uint32_t item_size {0U}; // attacker controlled + + BOOST_TEST_EQ(item_size, 0U); // the unguarded divisor is zero + BOOST_TEST(bytes_to_write > 0U); +} + +// The identical division in safe types throws instead of trapping. +void safe_reproduction() +{ + const u32 bytes_to_write {4096U}; + const u32 item_size {0U}; + + BOOST_TEST_THROWS((void)(bytes_to_write / item_size), std::domain_error); + BOOST_TEST(!checked_div(bytes_to_write, item_size).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2015_3418_cwe369_xorg_putimage_divzero.cpp b/test/cve_corpus/cwe369/cve_2015_3418_cwe369_xorg_putimage_divzero.cpp new file mode 100644 index 0000000..ce3743b --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2015_3418_cwe369_xorg_putimage_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-3418 +// cwe: CWE-369 +// product: X.Org Server (ProcPutImage) +// version: xorg-server +// summary: Divide by zero in X.Org Server (ProcPutImage). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=1024, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-3418 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {1024U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {1024U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2015_6855_cwe369_qemu_ide_divzero.cpp b/test/cve_corpus/cwe369/cve_2015_6855_cwe369_qemu_ide_divzero.cpp new file mode 100644 index 0000000..0cc5468 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2015_6855_cwe369_qemu_ide_divzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-6855 +// cwe: CWE-369 +// product: QEMU (hw/ide/core.c ATAPI) +// version: see advisory +// summary: Divide by zero in ATAPI command handling crashes the guest. +// root-cause: division (transfer / block_size) with a zero block size +// root-cause-width: u32 +// trigger: transfer=2048, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-6855 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: An unrestricted ATAPI command yields a zero divisor in ide core arithmetic. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t transfer {2048U}; + const std::uint32_t block_size {0U}; + + BOOST_TEST_EQ(block_size, 0U); + BOOST_TEST(transfer > 0U); +} + +void safe_reproduction() +{ + const u32 transfer {2048U}; + const u32 block_size {0U}; + + BOOST_TEST_THROWS((void)(transfer / block_size), std::domain_error); + BOOST_TEST(!checked_div(transfer, block_size).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2015_7513_cwe369_kernel_kvm_divzero.cpp b/test/cve_corpus/cwe369/cve_2015_7513_cwe369_kernel_kvm_divzero.cpp new file mode 100644 index 0000000..485275a --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2015_7513_cwe369_kernel_kvm_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-7513 +// cwe: CWE-369 +// product: Linux kernel KVM (x86.c PIT) +// version: before 4.4 +// summary: Divide by zero in Linux kernel KVM (x86.c PIT). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=1193182, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-7513 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {1193182U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {1193182U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_10053_cwe369_imagemagick_tiff_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_10053_cwe369_imagemagick_tiff_divzero.cpp new file mode 100644 index 0000000..3022b77 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_10053_cwe369_imagemagick_tiff_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-10053 +// cwe: CWE-369 +// product: ImageMagick (coders/tiff.c) +// version: before 6.9.5-8 +// summary: Divide by zero in ImageMagick (coders/tiff.c). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=8, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-10053 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {8U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {8U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_10219_cwe369_ghostscript_intersect_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_10219_cwe369_ghostscript_intersect_divzero.cpp new file mode 100644 index 0000000..4462dc4 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_10219_cwe369_ghostscript_intersect_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-10219 +// cwe: CWE-369 +// product: Ghostscript (gxfill.c intersect) +// version: 9.20 +// summary: Divide by zero in Ghostscript (gxfill.c intersect). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=100, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-10219 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {100U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {100U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_10266_cwe369_libtiff_10266_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_10266_cwe369_libtiff_10266_divzero.cpp new file mode 100644 index 0000000..788d0c8 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_10266_cwe369_libtiff_10266_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-10266 +// cwe: CWE-369 +// product: LibTIFF (divide by zero) +// version: 4.0.7 +// summary: Divide by zero in LibTIFF (divide by zero). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=16, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-10266 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {16U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {16U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_10267_cwe369_libtiff_10267_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_10267_cwe369_libtiff_10267_divzero.cpp new file mode 100644 index 0000000..0efa5b0 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_10267_cwe369_libtiff_10267_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-10267 +// cwe: CWE-369 +// product: LibTIFF (divide by zero) +// version: 4.0.7 +// summary: Divide by zero in LibTIFF (divide by zero). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=24, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-10267 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {24U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {24U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value % divisor), std::domain_error); + BOOST_TEST(!checked_mod(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_3622_cwe369_libtiff_predict_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_3622_cwe369_libtiff_predict_divzero.cpp new file mode 100644 index 0000000..a8e7738 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_3622_cwe369_libtiff_predict_divzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-3622 +// cwe: CWE-369 +// product: LibTIFF (fpAcc in tif_predict.c) +// version: 4.0.6 and earlier +// summary: Divide by zero in the floating point predictor path. +// root-cause: division (stride / bytes_per_sample) with a zero bytes per sample +// root-cause-width: u32 +// trigger: stride=4096, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-3622 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: The predictor computes stride / bytes_per_sample with an unchecked zero divisor. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t stride {4096U}; + const std::uint32_t bytes_per_sample {0U}; + + BOOST_TEST_EQ(bytes_per_sample, 0U); + BOOST_TEST(stride > 0U); +} + +void safe_reproduction() +{ + const u32 stride {4096U}; + const u32 bytes_per_sample {0U}; + + BOOST_TEST_THROWS((void)(stride / bytes_per_sample), std::domain_error); + BOOST_TEST(!checked_div(stride, bytes_per_sample).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_3623_cwe369_libtiff_rgb2ycbcr_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_3623_cwe369_libtiff_rgb2ycbcr_divzero.cpp new file mode 100644 index 0000000..7b86dee --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_3623_cwe369_libtiff_rgb2ycbcr_divzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-3623 +// cwe: CWE-369 +// product: LibTIFF (rgb2ycbcr tool) +// version: 4.0.6 and earlier +// summary: Divide by zero via a zero subsampling value crashes the tool. +// root-cause: division (dimension / subsampling) with an attacker controlled zero subsampling +// root-cause-width: u32 +// trigger: dimension=1024, subsampling=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-3623 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A zero horizontal or vertical subsampling value reaches a division. Modeled at u32. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t dimension {1024U}; + const std::uint32_t subsampling {0U}; // attacker controlled + + BOOST_TEST_EQ(subsampling, 0U); + BOOST_TEST(dimension > 0U); +} + +void safe_reproduction() +{ + const u32 dimension {1024U}; + const u32 subsampling {0U}; + + BOOST_TEST_THROWS((void)(dimension / subsampling), std::domain_error); + BOOST_TEST(!checked_div(dimension, subsampling).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_4797_cwe369_openjpeg_tcd_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_4797_cwe369_openjpeg_tcd_divzero.cpp new file mode 100644 index 0000000..a1e4f87 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_4797_cwe369_openjpeg_tcd_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-4797 +// cwe: CWE-369 +// product: OpenJPEG (tcd.c opj_tcd_init_tile) +// version: before the fix +// summary: Divide by zero in OpenJPEG (tcd.c opj_tcd_init_tile). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=512, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-4797 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {512U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {512U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_5323_cwe369_libtiff_fax3_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_5323_cwe369_libtiff_fax3_divzero.cpp new file mode 100644 index 0000000..e63c1dd --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_5323_cwe369_libtiff_fax3_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-5323 +// cwe: CWE-369 +// product: LibTIFF (_TIFFFax3fillruns) +// version: before 4.0.6 +// summary: Divide by zero in LibTIFF (_TIFFFax3fillruns). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=640, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-5323 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {640U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {640U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value % divisor), std::domain_error); + BOOST_TEST(!checked_mod(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_6505_cwe369_wireshark_packetbb_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_6505_cwe369_wireshark_packetbb_divzero.cpp new file mode 100644 index 0000000..abb4fc1 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_6505_cwe369_wireshark_packetbb_divzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-6505 +// cwe: CWE-369 +// product: Wireshark (packet-packetbb.c) +// version: 1.12.x before 1.12.13, 2.x before 2.0.5 +// summary: Divide by zero in the PacketBB dissector. +// root-cause: division (value / count) with an attacker controlled zero count +// root-cause-width: u32 +// trigger: value=256, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-6505 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: The PacketBB dissector divides by an attacker controlled count. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {256U}; + const std::uint32_t count {0U}; + + BOOST_TEST_EQ(count, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {256U}; + const u32 count {0U}; + + BOOST_TEST_THROWS((void)(value / count), std::domain_error); + BOOST_TEST(!checked_div(value, count).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_7499_cwe369_libav_aacsbr_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_7499_cwe369_libav_aacsbr_divzero.cpp new file mode 100644 index 0000000..77ab969 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_7499_cwe369_libav_aacsbr_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-7499 +// cwe: CWE-369 +// product: Libav (aacsbr.c) +// version: Libav 11.7 +// summary: Divide by zero in Libav (aacsbr.c). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=44100, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-7499 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {44100U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {44100U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_8667_cwe369_qemu_rc4030_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_8667_cwe369_qemu_rc4030_divzero.cpp new file mode 100644 index 0000000..46c3da0 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_8667_cwe369_qemu_rc4030_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-8667 +// cwe: CWE-369 +// product: QEMU (rc4030) +// version: QEMU +// summary: Divide by zero in QEMU (rc4030). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=4096, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-8667 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {4096U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {4096U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_8669_cwe369_qemu_serial_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_8669_cwe369_qemu_serial_divzero.cpp new file mode 100644 index 0000000..fd61329 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_8669_cwe369_qemu_serial_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-8669 +// cwe: CWE-369 +// product: QEMU (serial_update_parameters) +// version: QEMU +// summary: Divide by zero in QEMU (serial_update_parameters). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=115200, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-8669 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {115200U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {115200U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_8691_cwe369_jasper_siz_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_8691_cwe369_jasper_siz_divzero.cpp new file mode 100644 index 0000000..d70b570 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_8691_cwe369_jasper_siz_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-8691 +// cwe: CWE-369 +// product: JasPer (jpc_dec_process_siz) +// version: before 1.900.4 +// summary: Divide by zero in JasPer (jpc_dec_process_siz). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=256, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-8691 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {256U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {256U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_8697_cwe369_potrace_bmnew_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_8697_cwe369_potrace_bmnew_divzero.cpp new file mode 100644 index 0000000..7e81993 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_8697_cwe369_potrace_bmnew_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-8697 +// cwe: CWE-369 +// product: potrace (bitmap.h bm_new) +// version: before 1.13 +// summary: Divide by zero in potrace (bitmap.h bm_new). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=4096, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-8697 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {4096U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {4096U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_9112_cwe369_openjpeg_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_9112_cwe369_openjpeg_divzero.cpp new file mode 100644 index 0000000..f8fd233 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_9112_cwe369_openjpeg_divzero.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-9112 +// cwe: CWE-369 +// product: OpenJPEG (opj_pi_next_cprl in openjp2/pi.c) +// version: 2.1.2 +// summary: Floating point exception (divide by zero) in progression order iteration. +// root-cause: division by a zero step derived from crafted component parameters +// root-cause-width: u32 +// trigger: numerator=65536, step=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-9112 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted component yields a zero step used as a divisor in pi.c. Modeled at u32. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t numerator {65536U}; + const std::uint32_t step {0U}; // attacker controlled + + BOOST_TEST_EQ(step, 0U); + BOOST_TEST(numerator > 0U); +} + +void safe_reproduction() +{ + const u32 numerator {65536U}; + const u32 step {0U}; + + BOOST_TEST_THROWS((void)(numerator / step), std::domain_error); + BOOST_TEST(!checked_div(numerator, step).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_9265_cwe369_libming_mp3_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_9265_cwe369_libming_mp3_divzero.cpp new file mode 100644 index 0000000..c7e5f68 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_9265_cwe369_libming_mp3_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-9265 +// cwe: CWE-369 +// product: Libming (listmp3.c) +// version: 0.4.7 +// summary: Divide by zero in Libming (listmp3.c). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=1152, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-9265 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {1152U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {1152U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2016_9922_cwe369_qemu_cirrus_divzero.cpp b/test/cve_corpus/cwe369/cve_2016_9922_cwe369_qemu_cirrus_divzero.cpp new file mode 100644 index 0000000..8aaa94c --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2016_9922_cwe369_qemu_cirrus_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-9922 +// cwe: CWE-369 +// product: QEMU (cirrus_do_copy) +// version: QEMU +// summary: Divide by zero in QEMU (cirrus_do_copy). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=320, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-9922 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {320U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {320U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2017_6833_cwe369_audiofile_runpull_divzero.cpp b/test/cve_corpus/cwe369/cve_2017_6833_cwe369_audiofile_runpull_divzero.cpp new file mode 100644 index 0000000..dc9a012 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2017_6833_cwe369_audiofile_runpull_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-6833 +// cwe: CWE-369 +// product: Audio File Library (BlockCodec runPull) +// version: audiofile +// summary: Divide by zero in Audio File Library (BlockCodec runPull). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=2048, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-6833 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {2048U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {2048U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2017_6835_cwe369_audiofile_reset1_divzero.cpp b/test/cve_corpus/cwe369/cve_2017_6835_cwe369_audiofile_reset1_divzero.cpp new file mode 100644 index 0000000..facff7c --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2017_6835_cwe369_audiofile_reset1_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-6835 +// cwe: CWE-369 +// product: Audio File Library (BlockCodec reset1) +// version: audiofile +// summary: Divide by zero in Audio File Library (BlockCodec reset1). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=1024, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-6835 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {1024U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {1024U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value % divisor), std::domain_error); + BOOST_TEST(!checked_mod(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2017_7448_cwe369_lepton_fb_divzero.cpp b/test/cve_corpus/cwe369/cve_2017_7448_cwe369_lepton_fb_divzero.cpp new file mode 100644 index 0000000..c2eea3d --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2017_7448_cwe369_lepton_fb_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-7448 +// cwe: CWE-369 +// product: Dropbox Lepton (uncompressed_components.hh) +// version: Lepton +// summary: Divide by zero in Dropbox Lepton (uncompressed_components.hh). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=16384, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-7448 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {16384U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {16384U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2017_7595_cwe369_libtiff_jpeg_divzero.cpp b/test/cve_corpus/cwe369/cve_2017_7595_cwe369_libtiff_jpeg_divzero.cpp new file mode 100644 index 0000000..4658d61 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2017_7595_cwe369_libtiff_jpeg_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-7595 +// cwe: CWE-369 +// product: LibTIFF (tif_jpeg.c JPEGSetupEncode) +// version: 4.0.7 +// summary: Divide by zero in LibTIFF (tif_jpeg.c JPEGSetupEncode). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=3, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-7595 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {3U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {3U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe369/cve_2017_7962_cwe369_imageworsener_gif_divzero.cpp b/test/cve_corpus/cwe369/cve_2017_7962_cwe369_imageworsener_gif_divzero.cpp new file mode 100644 index 0000000..4517414 --- /dev/null +++ b/test/cve_corpus/cwe369/cve_2017_7962_cwe369_imageworsener_gif_divzero.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-7962 +// cwe: CWE-369 +// product: ImageWorsener (imagew-gif.c) +// version: 1.3.0 +// summary: Divide by zero in ImageWorsener (imagew-gif.c). +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=90, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-7962 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-369&resultsPerPage=200&startIndex=0 +// notes: A crafted input yields a zero divisor. +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {90U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {90U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +void bounded_reproduction() +{ + // A divisor required to be non zero is declared with a minimum of one; the + // zero divisor is rejected before the division can trap. + using nonzero_divisor = bounded_uint<1u, 1000000000u>; + std::uint32_t attacker_divisor {0U}; + BOOST_TEST_THROWS((nonzero_divisor{u32{attacker_divisor}}), std::domain_error); + BOOST_TEST_NO_THROW((void)nonzero_divisor{u32{7U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2007_4268_cwe681_apple_net_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2007_4268_cwe681_apple_net_signedness.cpp new file mode 100644 index 0000000..930af27 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2007_4268_cwe681_apple_net_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2007-4268 +// cwe: CWE-681 +// product: Apple Mac OS X Networking +// version: 10.4 through 10.4.10 +// summary: Integer signedness error allows local code execution. +// root-cause: a negative signed length is compared against an unsigned bound +// root-cause-width: mixed +// trigger: signed_length=-1 compared against an unsigned bound +// consequence: the check is bypassed then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2007-4268 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Comparing a signed and an unsigned safe type is ill-formed, surfacing the negative length. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {1024U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2008_1721_cwe681_python_zlib_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2008_1721_cwe681_python_zlib_signedness.cpp new file mode 100644 index 0000000..6aa9e5c --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2008_1721_cwe681_python_zlib_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2008-1721 +// cwe: CWE-681 +// product: CPython zlib extension module +// version: 2.5.2 and earlier +// summary: Integer signedness error allows code execution via a negative signed value. +// root-cause: a negative signed length is compared against an unsigned bound (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_length=-1 compared against an unsigned limit +// consequence: the check is bypassed then a heap buffer overflow +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2008-1721 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Comparing a signed and an unsigned safe type is ill-formed, so the developer +// notes: must resolve the signedness explicitly, which surfaces the negative length. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_length {-1}; // a negative length produced by the signedness bug + const u32 declared_limit {1024U}; + + // Ill-formed: a mixed signedness comparison between i32 and u32 is rejected. + // In native C the negative length converts to a huge unsigned and passes the check. + return (signed_length < declared_limit) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2009_0231_cwe681_windows_eot_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2009_0231_cwe681_windows_eot_signedness.cpp new file mode 100644 index 0000000..4a946cf --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2009_0231_cwe681_windows_eot_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2009-0231 +// cwe: CWE-681 +// product: Microsoft Windows (T2EMBED.DLL EOT) +// version: multiple +// summary: Incorrect numeric conversion in Microsoft Windows (T2EMBED.DLL EOT). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2009-0231 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Signedness error in the EOT font engine. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {1024U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2015_3406_cwe681_module_signature_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2015_3406_cwe681_module_signature_signedness.cpp new file mode 100644 index 0000000..d4f3874 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2015_3406_cwe681_module_signature_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2015-3406 +// cwe: CWE-681 +// product: Module::Signature (Perl) +// version: before 0.74 +// summary: Incorrect numeric conversion in Module::Signature (Perl). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2015-3406 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Unsigned portion treated as signed in signature parsing. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {256U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2016_3074_cwe681_libgd_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2016_3074_cwe681_libgd_signedness.cpp new file mode 100644 index 0000000..6836970 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2016_3074_cwe681_libgd_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-3074 +// cwe: CWE-681 +// product: GD Graphics Library (libgd) +// version: 2.1.1 +// summary: Integer signedness error allows denial of service or code execution. +// root-cause: a signed size is added to an unsigned offset (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: a negative signed chunk size combined with an unsigned offset +// consequence: out of bounds access from the mishandled signed value +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-3074 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Mixed signedness arithmetic between i32 and u32 is ill-formed, forcing the +// notes: developer to resolve the signedness rather than let the implicit rule hide it. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 chunk_size {-4}; // a negative size produced by the signedness bug + const u32 base_offset {16U}; + + // Ill-formed: mixed signedness addition between i32 and u32 is rejected. + const auto next = chunk_size + base_offset; + return static_cast(next == u32{12U}) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2018_1000224_cwe681_godot_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2018_1000224_cwe681_godot_signedness.cpp new file mode 100644 index 0000000..cbb3243 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2018_1000224_cwe681_godot_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-1000224 +// cwe: CWE-681 +// product: Godot Engine +// version: before 2.1.5 +// summary: Incorrect numeric conversion in Godot Engine. +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-1000224 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Signed/unsigned comparison with a wrong buffer size. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {8192U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2018_11262_cwe681_android_qrd_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2018_11262_cwe681_android_qrd_signedness.cpp new file mode 100644 index 0000000..bc574e2 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2018_11262_cwe681_android_qrd_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-11262 +// cwe: CWE-681 +// product: Android for MSM (QRD) +// version: see advisory +// summary: Incorrect numeric conversion in Android for MSM (QRD). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-11262 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Integer signedness error in a length check. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {1024U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2018_5251_cwe681_libming_sbits_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2018_5251_cwe681_libming_sbits_signedness.cpp new file mode 100644 index 0000000..7d77f40 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2018_5251_cwe681_libming_sbits_signedness.cpp @@ -0,0 +1,49 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-5251 +// cwe: CWE-681 +// product: libming (readSBits) +// version: 0.4.8 +// summary: Incorrect numeric conversion in libming (readSBits). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-4 combined with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-5251 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Left shift of a negative value (signedness error). +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-4}; + const u32 unsigned_bound {16U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + const auto combined = signed_value + unsigned_bound; + return static_cast(combined == u32{0U}) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2018_5711_cwe681_libgd_gif_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2018_5711_cwe681_libgd_gif_signedness.cpp new file mode 100644 index 0000000..b39c296 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2018_5711_cwe681_libgd_gif_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-5711 +// cwe: CWE-681 +// product: GD Graphics Library (gd_gif_in.c) +// version: libgd +// summary: Incorrect numeric conversion in GD Graphics Library (gd_gif_in.c). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-5711 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Signed/unsigned confusion in GIF handling. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {4096U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2019_1010204_cwe681_binutils_gold_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2019_1010204_cwe681_binutils_gold_signedness.cpp new file mode 100644 index 0000000..34a39bd --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2019_1010204_cwe681_binutils_gold_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-1010204 +// cwe: CWE-681 +// product: GNU binutils gold +// version: 2.21 through 2.31.1 +// summary: Signed/unsigned comparison leads to an out of bounds read. +// root-cause: a signed size is compared against an unsigned bound (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_size=-1 compared against an unsigned bound +// consequence: out of bounds read +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-1010204 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: The signed versus unsigned comparison in gold is ill-formed for safe types. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {2048U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2019_14842_cwe681_nbd_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2019_14842_cwe681_nbd_signedness.cpp new file mode 100644 index 0000000..b9828f0 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2019_14842_cwe681_nbd_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-14842 +// cwe: CWE-681 +// product: NBD (structured reply) +// version: see advisory +// summary: Incorrect numeric conversion in NBD (structured reply). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-14842 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A bounds check is defeated by signed/unsigned confusion. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {2048U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2019_19945_cwe681_openwrt_uhttpd_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2019_19945_cwe681_openwrt_uhttpd_signedness.cpp new file mode 100644 index 0000000..c989d42 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2019_19945_cwe681_openwrt_uhttpd_signedness.cpp @@ -0,0 +1,49 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-19945 +// cwe: CWE-681 +// product: OpenWrt uhttpd +// version: through 18.06.5 and 19.x through 19.07.0-rc2 +// summary: Integer signedness error leads to out of bounds access. +// root-cause: a negative signed length is added to an unsigned offset +// root-cause-width: mixed +// trigger: signed_length=-8 combined with an unsigned offset +// consequence: out of bounds heap access +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-19945 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Mixed signedness arithmetic between i32 and u32 is ill-formed for safe types. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-8}; + const u32 unsigned_bound {16U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + const auto combined = signed_value + unsigned_bound; + return static_cast(combined == u32{0U}) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2019_7310_cwe681_poppler_xref_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2019_7310_cwe681_poppler_xref_signedness.cpp new file mode 100644 index 0000000..0466290 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2019_7310_cwe681_poppler_xref_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-7310 +// cwe: CWE-681 +// product: Poppler (XRef::getEntry in XRef.cc) +// version: 0.73.0 +// summary: Heap over-read from an integer signedness error in XRef handling. +// root-cause: a negative signed index is compared against an unsigned table size +// root-cause-width: mixed +// trigger: signed_index=-1 compared against an unsigned size +// consequence: out of bounds read +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-7310 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: The signed index versus unsigned size comparison is ill-formed for safe types. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {4096U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2020_13545_cwe681_textmaker_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2020_13545_cwe681_textmaker_signedness.cpp new file mode 100644 index 0000000..7b2bf21 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2020_13545_cwe681_textmaker_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2020-13545 +// cwe: CWE-681 +// product: TextMaker (document parsing) +// version: see advisory +// summary: Incorrect numeric conversion in TextMaker (document parsing). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2020-13545 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Signed conversion mishandles a length. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {4096U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2020_1913_cwe681_hermes_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2020_1913_cwe681_hermes_signedness.cpp new file mode 100644 index 0000000..35cc119 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2020_1913_cwe681_hermes_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2020-1913 +// cwe: CWE-681 +// product: Facebook Hermes (JS interpreter) +// version: before the fix +// summary: Incorrect numeric conversion in Facebook Hermes (JS interpreter). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2020-1913 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Integer signedness error in the interpreter. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {1024U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2021_27219_cwe681_glib_bytearray_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2021_27219_cwe681_glib_bytearray_signedness.cpp new file mode 100644 index 0000000..0072a19 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2021_27219_cwe681_glib_bytearray_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2021-27219 +// cwe: CWE-681 +// product: GNOME GLib (g_byte_array) +// version: before 2.66.7 +// summary: Incorrect numeric conversion in GNOME GLib (g_byte_array). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2021-27219 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Signed/unsigned confusion in byte array sizing. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {65535U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/compile_fail_cve_2022_27882_cwe681_openbsd_slaacd_signedness.cpp b/test/cve_corpus/cwe681/compile_fail_cve_2022_27882_cwe681_openbsd_slaacd_signedness.cpp new file mode 100644 index 0000000..e5333d1 --- /dev/null +++ b/test/cve_corpus/cwe681/compile_fail_cve_2022_27882_cwe681_openbsd_slaacd_signedness.cpp @@ -0,0 +1,48 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2022-27882 +// cwe: CWE-681 +// product: OpenBSD (slaacd) +// version: 6.9 and 7.0 +// summary: Incorrect numeric conversion in OpenBSD (slaacd). +// root-cause: a signed value combined with an unsigned value (signed/unsigned confusion) +// root-cause-width: mixed +// trigger: signed_value=-1 compared with an unsigned bound +// consequence: check bypass then memory corruption +// classification: PREVENTED_COMPILETIME +// expected-exception: none +// tier-form: compile-fail +// reference: https://nvd.nist.gov/vuln/detail/CVE-2022-27882 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Integer signedness error in slaacd. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +int main() +{ + const i32 signed_value {-1}; + const u32 unsigned_bound {512U}; + + // Ill-formed: a mixed signedness operation between i32 and u32 is rejected, + // forcing the developer to resolve the signedness that hides the defect. + return (signed_value < unsigned_bound) ? 1 : 0; +} diff --git a/test/cve_corpus/cwe681/cve_2008_3282_cwe681_openoffice_alloc_truncation.cpp b/test/cve_corpus/cwe681/cve_2008_3282_cwe681_openoffice_alloc_truncation.cpp new file mode 100644 index 0000000..95cb3a4 --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2008_3282_cwe681_openoffice_alloc_truncation.cpp @@ -0,0 +1,74 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2008-3282 +// cwe: CWE-681 +// product: OpenOffice.org (rtl_allocateMemory, 64-bit) +// version: 2.4.1 +// summary: Integer overflow and truncation in the memory allocator on 64-bit. +// root-cause: a 64-bit allocation size is truncated when stored into a 32-bit field +// root-cause-width: mixed +// trigger: size=4294967300 stored into a 32-bit field +// consequence: undersized allocation then heap overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2008-3282 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A 64-bit size is narrowed to a 32-bit field. Modeled as u64 to u32. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint64_t value {4294967300ULL}; + const std::uint32_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, 4U); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u64 value {4294967300ULL}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2017_12140_cwe681_imagemagick_dcm_truncation.cpp b/test/cve_corpus/cwe681/cve_2017_12140_cwe681_imagemagick_dcm_truncation.cpp new file mode 100644 index 0000000..d3eecaa --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2017_12140_cwe681_imagemagick_dcm_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-12140 +// cwe: CWE-681 +// product: ImageMagick (coders/dcm.c) +// version: 7.0.6-1 +// summary: Incorrect numeric conversion in ImageMagick (coders/dcm.c). +// root-cause: a 64-bit value stored into a 32-bit field, truncating it +// root-cause-width: mixed +// trigger: value=5000000001 into a 32-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-12140 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A large signed value narrows through a 32-bit field. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint64_t value {5000000001ULL}; + const std::uint32_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, 705032705U); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u64 value {5000000001ULL}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2017_7308_cwe681_kernel_afpacket_truncation.cpp b/test/cve_corpus/cwe681/cve_2017_7308_cwe681_kernel_afpacket_truncation.cpp new file mode 100644 index 0000000..109299e --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2017_7308_cwe681_kernel_afpacket_truncation.cpp @@ -0,0 +1,74 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-7308 +// cwe: CWE-681 +// product: Linux kernel (packet_set_ring in af_packet.c) +// version: through 4.10.6 +// summary: Truncated block-size validation leads to a heap overflow. +// root-cause: a 32-bit block size is stored into a 16-bit field, truncating the value +// root-cause-width: mixed +// trigger: block_size=70000 stored into a 16-bit field +// consequence: undersized ring block then heap buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-7308 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: The block-size field is narrowed; modeled as a 32-bit to 16-bit narrowing. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {70000U}; + const std::uint16_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, static_cast(4464U)); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u32 value {70000U}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2018_3999_cwe681_atlantis_jpeg_truncation.cpp b/test/cve_corpus/cwe681/cve_2018_3999_cwe681_atlantis_jpeg_truncation.cpp new file mode 100644 index 0000000..5e96885 --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2018_3999_cwe681_atlantis_jpeg_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-3999 +// cwe: CWE-681 +// product: Atlantis Word Processor (JPEG parser) +// version: 3.2.5.0 +// summary: Incorrect numeric conversion in Atlantis Word Processor (JPEG parser). +// root-cause: a wider value stored into a narrower field, truncating it +// root-cause-width: mixed +// trigger: value=90000 into a 16-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-3999 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A 32-bit value is truncated to a 16-bit field. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {90000U}; + const std::uint16_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, static_cast(24464U)); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u32 value {90000U}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2018_8786_cwe681_freerdp_bitmap_truncation.cpp b/test/cve_corpus/cwe681/cve_2018_8786_cwe681_freerdp_bitmap_truncation.cpp new file mode 100644 index 0000000..2c0347d --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2018_8786_cwe681_freerdp_bitmap_truncation.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-8786 +// cwe: CWE-681 +// product: FreeRDP (update_read_bitmap_update) +// version: before 2.0.0-rc4 +// summary: Integer truncation leads to a heap based buffer overflow in bitmap update parsing. +// root-cause: a 32-bit rectangle count is stored into a 16-bit field, truncating the value +// root-cause-width: mixed +// trigger: count=70000 stored into a 16-bit field (truncates to 4464) +// consequence: undersized allocation from the truncated count then heap buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-8786 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Compute at matched width; the checked narrowing to a 16-bit field throws. +// notes: The conversion check throws regardless of the type error policy. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +// Native code stores a 32-bit count into a 16-bit field, silently truncating it. +void native_reproduction() +{ + const std::uint32_t count {70000U}; + const std::uint16_t field {static_cast(count)}; // silent truncation + + BOOST_TEST_EQ(field, static_cast(4464U)); // 70000 mod 65536 + BOOST_TEST(static_cast(field) != count); // lost the high bits + BOOST_TEST(static_cast(field) < count); // undercount +} + +// The identical narrowing in safe types throws instead of silently truncating. +void safe_reproduction() +{ + const u32 count {70000U}; + + BOOST_TEST_THROWS((void)static_cast(count), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2019_10624_cwe681_libiec_u8_truncation.cpp b/test/cve_corpus/cwe681/cve_2019_10624_cwe681_libiec_u8_truncation.cpp new file mode 100644 index 0000000..233b79d --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2019_10624_cwe681_libiec_u8_truncation.cpp @@ -0,0 +1,74 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-10624 +// cwe: CWE-681 +// product: Qualcomm vendor command handler +// version: see advisory +// summary: Integer truncation copying an int length into a u8 field yields a buffer overflow. +// root-cause: a wide length is stored into an 8-bit field, truncating the value +// root-cause-width: mixed +// trigger: length=300 stored into an 8-bit field (truncates to 44) +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-10624 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: Compute at matched width; the checked narrowing to an 8-bit field throws. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t length {300U}; + const std::uint8_t field {static_cast(length)}; // silent truncation + + BOOST_TEST_EQ(field, static_cast(44U)); // 300 mod 256 + BOOST_TEST(static_cast(field) != length); + BOOST_TEST(static_cast(field) < length); +} + +void safe_reproduction() +{ + const u32 length {300U}; + + BOOST_TEST_THROWS((void)static_cast(length), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2019_14563_cwe681_edk2_truncation.cpp b/test/cve_corpus/cwe681/cve_2019_14563_cwe681_edk2_truncation.cpp new file mode 100644 index 0000000..bfa06d1 --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2019_14563_cwe681_edk2_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-14563 +// cwe: CWE-681 +// product: EDK II +// version: see advisory +// summary: Incorrect numeric conversion in EDK II. +// root-cause: a 64-bit value stored into a 32-bit field, truncating it +// root-cause-width: mixed +// trigger: value=5000000000 into a 32-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-14563 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A 64-bit value is truncated to 32 bits. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint64_t value {5000000000ULL}; + const std::uint32_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, 705032704U); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u64 value {5000000000ULL}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2019_16778_cwe681_tensorflow_index_truncation.cpp b/test/cve_corpus/cwe681/cve_2019_16778_cwe681_tensorflow_index_truncation.cpp new file mode 100644 index 0000000..7d8e8db --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2019_16778_cwe681_tensorflow_index_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-16778 +// cwe: CWE-681 +// product: TensorFlow (UnsortedSegmentSum) +// version: before 1.15 +// summary: Heap buffer overflow from a 32-bit index truncation. +// root-cause: a 64-bit index is stored into a 32-bit field, truncating the value +// root-cause-width: mixed +// trigger: index=5000000000 stored into a 32-bit field +// consequence: undersized index then heap buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-16778 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: With an int32 index argument a 64-bit value is truncated. Modeled as u64 to u32. +// notes: The conversion check throws regardless of the type error policy. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint64_t value {5000000000ULL}; + const std::uint32_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, 705032704U); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u64 value {5000000000ULL}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2019_19958_cwe681_libiec_str_truncation.cpp b/test/cve_corpus/cwe681/cve_2019_19958_cwe681_libiec_str_truncation.cpp new file mode 100644 index 0000000..88283b2 --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2019_19958_cwe681_libiec_str_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2019-19958 +// cwe: CWE-681 +// product: libIEC61850 (StringUtils) +// version: 1.4.0 +// summary: Incorrect numeric conversion in libIEC61850 (StringUtils). +// root-cause: a wider value stored into a narrower field, truncating it +// root-cause-width: mixed +// trigger: value=300 into an 8-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2019-19958 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A wide length is truncated to an 8-bit field. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {300U}; + const std::uint8_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, static_cast(44U)); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u32 value {300U}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2020_4032_cwe681_freerdp_updaterecv_truncation.cpp b/test/cve_corpus/cwe681/cve_2020_4032_cwe681_freerdp_updaterecv_truncation.cpp new file mode 100644 index 0000000..09134ac --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2020_4032_cwe681_freerdp_updaterecv_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2020-4032 +// cwe: CWE-681 +// product: FreeRDP (update_recv) +// version: before 2.1.2 +// summary: Incorrect numeric conversion in FreeRDP (update_recv). +// root-cause: a wider value stored into a narrower field, truncating it +// root-cause-width: mixed +// trigger: value=70000 into a 16-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2020-4032 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A 32-bit value is truncated to a 16-bit field. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {70000U}; + const std::uint16_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, static_cast(4464U)); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u32 value {70000U}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2021_21860_cwe681_mpeg4_21860_truncation.cpp b/test/cve_corpus/cwe681/cve_2021_21860_cwe681_mpeg4_21860_truncation.cpp new file mode 100644 index 0000000..5c87e59 --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2021_21860_cwe681_mpeg4_21860_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2021-21860 +// cwe: CWE-681 +// product: MPEG-4 decoder +// version: see advisory +// summary: Incorrect numeric conversion in MPEG-4 decoder. +// root-cause: a wider value stored into a narrower field, truncating it +// root-cause-width: mixed +// trigger: value=80000 into a 16-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2021-21860 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A 32-bit value is truncated to a 16-bit field. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {80000U}; + const std::uint16_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, static_cast(14464U)); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u32 value {80000U}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2021_21861_cwe681_mpeg4_21861_truncation.cpp b/test/cve_corpus/cwe681/cve_2021_21861_cwe681_mpeg4_21861_truncation.cpp new file mode 100644 index 0000000..64252de --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2021_21861_cwe681_mpeg4_21861_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2021-21861 +// cwe: CWE-681 +// product: MPEG-4 decoder +// version: see advisory +// summary: Incorrect numeric conversion in MPEG-4 decoder. +// root-cause: a wider value stored into a narrower field, truncating it +// root-cause-width: mixed +// trigger: value=100000 into a 16-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2021-21861 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A 32-bit value is truncated to a 16-bit field. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {100000U}; + const std::uint16_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, static_cast(34464U)); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u32 value {100000U}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe681/cve_2021_36357_cwe681_openpower_ts_truncation.cpp b/test/cve_corpus/cwe681/cve_2021_36357_cwe681_openpower_ts_truncation.cpp new file mode 100644 index 0000000..87ed6bb --- /dev/null +++ b/test/cve_corpus/cwe681/cve_2021_36357_cwe681_openpower_ts_truncation.cpp @@ -0,0 +1,75 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2021-36357 +// cwe: CWE-681 +// product: OpenPOWER firmware (unpack_timestamp) +// version: OpenPOWER 2.6 +// summary: Incorrect numeric conversion in OpenPOWER firmware (unpack_timestamp). +// root-cause: a 64-bit value stored into a 32-bit field, truncating it +// root-cause-width: mixed +// trigger: value=6000000000 into a 32-bit field +// consequence: undersized field then buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2021-36357 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-681&resultsPerPage=200&startIndex=0 +// notes: A 64-bit value is truncated by a 32-bit conversion. +// notes: Modeled at the canonical truncation pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint64_t value {6000000000ULL}; + const std::uint32_t field {static_cast(value)}; + + BOOST_TEST_EQ(field, 1705032704U); + BOOST_TEST(static_cast(field) != value); + BOOST_TEST(static_cast(field) < value); +} + +void safe_reproduction() +{ + const u64 value {6000000000ULL}; + + BOOST_TEST_THROWS((void)static_cast(value), std::domain_error); +} + +void bounded_reproduction() +{ + // Declaring the input with its documented maximum rejects the oversized + // value at construction, before the operation can misbehave. + using bounded_input = bounded_uint<0u, 1000000u>; + std::uint32_t attacker_input {2000000000U}; + BOOST_TEST_THROWS((bounded_input{u32{attacker_input}}), std::domain_error); + BOOST_TEST_NO_THROW((void)bounded_input{u32{1000U}}); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + bounded_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2011_1573_cwe682_kernel_sctp_bounded.cpp b/test/cve_corpus/cwe682/cve_2011_1573_cwe682_kernel_sctp_bounded.cpp new file mode 100644 index 0000000..bbf4477 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2011_1573_cwe682_kernel_sctp_bounded.cpp @@ -0,0 +1,77 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2011-1573 +// cwe: CWE-682 +// product: Linux kernel SCTP (sm_make_chunk.c) +// version: before 2.6.34 +// summary: Incorrect length accounting yields a length larger than the available space. +// root-cause: a remaining length omits a term, exceeding the known available buffer +// root-cause-width: u8 +// trigger: available=20 bytes, remaining computed as total=64 - used=40 = 24 (padding omitted) +// consequence: an over long length drives an out of bounds read or write +// classification: PREVENTED_BOUNDED +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2011-1573 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: The subtraction 64 - 40 is correct arithmetic and does not underflow, so the +// notes: default check does not fire. The defect is that the result exceeds the real +// notes: available space. Bounding the length by the known available size (bounded_uint +// notes: <0, 20>) rejects the over long value before it is used. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +// The real available space is 20 bytes, so a valid length is 0 through 20. +using chunk_length = bounded_uint<0U, 20U>; + +void native_reproduction() +{ + const std::uint32_t available {20U}; + const std::uint32_t total {64U}; + const std::uint32_t used {40U}; // omits the padding term (the bug) + const std::uint32_t remaining {total - used}; // 24, no underflow + + BOOST_TEST_EQ(remaining, 24U); + BOOST_TEST(remaining > available); // claims more space than exists +} + +void safe_reproduction() +{ + const u8 total {64U}; + const u8 used {40U}; + + // The subtraction is correct and does not underflow: the default check stays silent. + BOOST_TEST_NO_THROW((void)(total - used)); + const u8 remaining {total - used}; // u8{24} + + // Bounding the length by the known available space rejects the over long value. + BOOST_TEST_THROWS((chunk_length{remaining}), std::domain_error); + BOOST_TEST_NO_THROW((void)chunk_length{u8{20U}}); // a length within the buffer is accepted +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2011_3062_cwe682_ots_offbyone_bounded.cpp b/test/cve_corpus/cwe682/cve_2011_3062_cwe682_ots_offbyone_bounded.cpp new file mode 100644 index 0000000..6320a28 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2011_3062_cwe682_ots_offbyone_bounded.cpp @@ -0,0 +1,82 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2011-3062 +// cwe: CWE-682 +// product: OpenType Sanitizer (as used in Google Chrome) +// version: before 18.0.1025.142 +// summary: Off by one error in the OpenType Sanitizer allows an out of bounds access. +// root-cause: an index is computed one too large for a buffer of known size +// root-cause-width: u8 +// trigger: buffer_size=150 (valid indices 0..149), computed index base=100 + length=50 = 150 +// consequence: one element out of bounds access +// classification: PREVENTED_BOUNDED +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2011-3062 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: The addition 100 + 50 is correct arithmetic and does not overflow, so the +// notes: default overflow check does not fire. The defect is that the result is used as +// notes: an index into a 150-element buffer. Declaring the index domain from the known +// notes: buffer size (bounded_uint<0, 149>) rejects the off-by-one value at the point it +// notes: is formed as an index. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +// The known buffer holds 150 elements, so the valid index domain is 0 through 149. +using table_index = bounded_uint<0U, 149U>; + +// Native code computes an inclusive end index and uses it directly; the addition is +// correct arithmetic, but the value is one past the last valid index. +void native_reproduction() +{ + const std::uint32_t buffer_size {150U}; + const std::uint32_t base {100U}; + const std::uint32_t length {50U}; + const std::uint32_t end_index {base + length}; // 150, no overflow + + BOOST_TEST_EQ(end_index, 150U); + BOOST_TEST(end_index >= buffer_size); // one past the last valid index (149) +} + +// The default arithmetic types do not catch this (the sum is representable), but expressing +// the index domain with a bounded type rejects the out of domain index. +void safe_reproduction() +{ + const u8 base {100U}; + const u8 length {50U}; + + // The arithmetic is correct and does not overflow: the default check stays silent. + BOOST_TEST_NO_THROW((void)(base + length)); + const u8 end_index {base + length}; // u8{150} + + // Materializing the value as a table index enforces the buffer's domain. + BOOST_TEST_THROWS((table_index{end_index}), std::domain_error); + BOOST_TEST_NO_THROW((void)table_index{u8{149U}}); // the last valid index is accepted +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2016_7433_cwe682_ntp_calc_notprevented.cpp b/test/cve_corpus/cwe682/cve_2016_7433_cwe682_ntp_calc_notprevented.cpp new file mode 100644 index 0000000..d0984ee --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2016_7433_cwe682_ntp_calc_notprevented.cpp @@ -0,0 +1,70 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2016-7433 +// cwe: CWE-682 +// product: NTP +// version: before 4.2.8p9 +// summary: Incorrect initial sync calculation allows an attacker to influence the clock. +// root-cause: a value is combined with the wrong operand; the arithmetic stays in range +// root-cause-width: u32 +// trigger: sum=7, count=2 with truncating integer division +// consequence: a wrong but in range result that skews the computed offset +// classification: NOT_PREVENTED +// expected-exception: none +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2016-7433 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: Honest limitation. Integer division is well defined and in range, so no fault is +// notes: raised; the defect is the formula (truncation where a rounded value was intended). +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t sum {7U}; + const std::uint32_t count {2U}; + + const std::uint32_t average {sum / count}; // 3, truncated (the bug) + const std::uint32_t rounded {(sum + count / 2U) / count}; // 4, the intended value + + BOOST_TEST_EQ(average, 3U); + BOOST_TEST(average != rounded); // wrong but in range +} + +// safe_numbers does not catch this: division is representable, so no fault, and the safe +// result equals the native truncated value. +void safe_reproduction() +{ + const u32 sum {7U}; + const u32 count {2U}; + + BOOST_TEST_NO_THROW((void)(sum / count)); + const u32 average {sum / count}; + BOOST_TEST_EQ(static_cast(average), 3U); // identical truncated value, not caught +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2017_11537_cwe682_imagemagick_palm_divzero.cpp b/test/cve_corpus/cwe682/cve_2017_11537_cwe682_imagemagick_palm_divzero.cpp new file mode 100644 index 0000000..bcb51b0 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2017_11537_cwe682_imagemagick_palm_divzero.cpp @@ -0,0 +1,65 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-11537 +// cwe: CWE-682 +// product: ImageMagick (WritePALMImage) +// version: 7.0.6-1 +// summary: Floating point exception (divide by zero) writing a PALM image. +// root-cause: division (value / depth) with a zero depth from crafted parameters +// root-cause-width: u32 +// trigger: value=65536, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-11537 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: NVD tags this CWE-682, but the disclosed root cause is a divide by zero, which the +// notes: library detects. It is counted under the CWE-682 control to keep the control honest. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {65536U}; + const std::uint32_t depth {0U}; + + BOOST_TEST_EQ(depth, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {65536U}; + const u32 depth {0U}; + + BOOST_TEST_THROWS((void)(value / depth), std::domain_error); + BOOST_TEST(!checked_div(value, depth).has_value()); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2017_8326_cwe682_imageworsener_shl_shl.cpp b/test/cve_corpus/cwe682/cve_2017_8326_cwe682_imageworsener_shl_shl.cpp new file mode 100644 index 0000000..860dd48 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2017_8326_cwe682_imageworsener_shl_shl.cpp @@ -0,0 +1,67 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-8326 +// cwe: CWE-682 +// product: ImageWorsener +// version: before 1.3.1 +// summary: Left shift overflow in ImageWorsener. +// root-cause: left shift whose result exceeds the type width +// root-cause-width: u32 +// trigger: value=16777215, shift=16 +// consequence: incorrect shifted value then memory corruption +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-8326 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: A left shift result exceeds the type width. +// notes: Modeled at the canonical shift overflow pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {16777215U}; + const std::uint32_t shift {16U}; + + const std::uint64_t true_result {static_cast(value) << shift}; + const std::uint32_t result {static_cast(value << shift)}; + + BOOST_TEST_EQ(result, 4294901760U); + BOOST_TEST(static_cast(result) != true_result); +} + +void safe_reproduction() +{ + const u32 value {16777215U}; + const u32 shift {16U}; + + BOOST_TEST_THROWS((void)(value << shift), std::overflow_error); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2017_8932_cwe682_go_p256_notprevented.cpp b/test/cve_corpus/cwe682/cve_2017_8932_cwe682_go_p256_notprevented.cpp new file mode 100644 index 0000000..2173d95 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2017_8932_cwe682_go_p256_notprevented.cpp @@ -0,0 +1,66 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2017-8932 +// cwe: CWE-682 +// product: Go crypto/elliptic (P-256 ScalarMult) +// version: Go before 1.7.6 +// summary: Incorrect P-256 ScalarMult result (in range). +// root-cause: integer division truncates; the result is in range and well defined +// root-cause-width: u32 +// trigger: numerator=7, divisor=2 +// consequence: undersized result that the library cannot detect +// classification: NOT_PREVENTED +// expected-exception: none +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2017-8932 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: In-range calculation error the library cannot detect. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t numerator {7U}; + const std::uint32_t divisor {2U}; + const std::uint32_t quotient {numerator / divisor}; + const std::uint32_t needed {(numerator + divisor - 1U) / divisor}; + + BOOST_TEST_EQ(quotient, 3U); + BOOST_TEST(quotient < needed); +} + +void safe_reproduction() +{ + const u32 numerator {7U}; + const u32 divisor {2U}; + + BOOST_TEST_NO_THROW((void)(numerator / divisor)); + const u32 quotient {numerator / divisor}; + BOOST_TEST_EQ(static_cast(quotient), 3U); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2018_11790_cwe682_apache_oo_bounded.cpp b/test/cve_corpus/cwe682/cve_2018_11790_cwe682_apache_oo_bounded.cpp new file mode 100644 index 0000000..ab6d674 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2018_11790_cwe682_apache_oo_bounded.cpp @@ -0,0 +1,76 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-11790 +// cwe: CWE-682 +// product: Apache OpenOffice +// version: 4.1.5 and earlier +// summary: An incorrect line-termination length yields an out of bounds read. +// root-cause: a computed offset exceeds a line buffer of known size +// root-cause-width: u8 +// trigger: buffer_size=200 (valid offsets 0..199), computed offset base=200 + extra=10 = 210 +// consequence: out of bounds read +// classification: PREVENTED_BOUNDED +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-11790 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: The addition is correct arithmetic and does not overflow, so the default check +// notes: does not fire. The defect is that the offset lands past a known line buffer. +// notes: Bounding the offset by the buffer size (bounded_uint<0, 199>) rejects it. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +// The line buffer holds 200 bytes, so the valid offset domain is 0 through 199. +using line_offset = bounded_uint<0U, 199U>; + +void native_reproduction() +{ + const std::uint32_t buffer_size {200U}; + const std::uint32_t base {200U}; + const std::uint32_t extra {10U}; + const std::uint32_t offset {base + extra}; // 210, no overflow + + BOOST_TEST_EQ(offset, 210U); + BOOST_TEST(offset >= buffer_size); // past the end of the line buffer +} + +void safe_reproduction() +{ + const u8 base {200U}; + const u8 extra {10U}; + + // The arithmetic is correct and does not overflow: the default check stays silent. + BOOST_TEST_NO_THROW((void)(base + extra)); + const u8 offset {base + extra}; // u8{210} + + // Bounding the offset by the known buffer size rejects the out of domain value. + BOOST_TEST_THROWS((line_offset{offset}), std::domain_error); + BOOST_TEST_NO_THROW((void)line_offset{u8{199U}}); // the last valid offset is accepted +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2018_14439_cwe682_eos4j_notprevented.cpp b/test/cve_corpus/cwe682/cve_2018_14439_cwe682_eos4j_notprevented.cpp new file mode 100644 index 0000000..2683380 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2018_14439_cwe682_eos4j_notprevented.cpp @@ -0,0 +1,66 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-14439 +// cwe: CWE-682 +// product: espritblock eos4j (EOS SDK) +// version: through 2018-07-12 +// summary: Mishandled numeric calculation in eos4j. +// root-cause: integer division truncates; the result is in range and well defined +// root-cause-width: u32 +// trigger: numerator=9, divisor=4 +// consequence: undersized result that the library cannot detect +// classification: NOT_PREVENTED +// expected-exception: none +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-14439 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: In-range calculation error the library cannot detect. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t numerator {9U}; + const std::uint32_t divisor {4U}; + const std::uint32_t quotient {numerator / divisor}; + const std::uint32_t needed {(numerator + divisor - 1U) / divisor}; + + BOOST_TEST_EQ(quotient, 2U); + BOOST_TEST(quotient < needed); +} + +void safe_reproduction() +{ + const u32 numerator {9U}; + const u32 divisor {4U}; + + BOOST_TEST_NO_THROW((void)(numerator / divisor)); + const u32 quotient {numerator / divisor}; + BOOST_TEST_EQ(static_cast(quotient), 2U); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2018_16781_cwe682_ffjpeg_divzero.cpp b/test/cve_corpus/cwe682/cve_2018_16781_cwe682_ffjpeg_divzero.cpp new file mode 100644 index 0000000..3dc2a98 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2018_16781_cwe682_ffjpeg_divzero.cpp @@ -0,0 +1,65 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-16781 +// cwe: CWE-682 +// product: ffjpeg +// version: before 2018-08-22 +// summary: Divide by zero (FPE) in ffjpeg. +// root-cause: division or modulo by an attacker controlled zero +// root-cause-width: u32 +// trigger: value=4096, divisor=0 +// consequence: divide by zero (SIGFPE) denial of service +// classification: PREVENTED_RUNTIME +// expected-exception: std::domain_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-16781 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: A crafted JPEG yields a zero divisor (FPE). +// notes: Modeled at the canonical divide by zero pattern for this CWE at the disclosed width. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t value {4096U}; + const std::uint32_t divisor {0U}; + + BOOST_TEST_EQ(divisor, 0U); + BOOST_TEST(value > 0U); +} + +void safe_reproduction() +{ + const u32 value {4096U}; + const u32 divisor {0U}; + + BOOST_TEST_THROWS((void)(value / divisor), std::domain_error); + BOOST_TEST(!checked_div(value, divisor).has_value()); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} diff --git a/test/cve_corpus/cwe682/cve_2018_20999_cwe682_orion_notprevented.cpp b/test/cve_corpus/cwe682/cve_2018_20999_cwe682_orion_notprevented.cpp new file mode 100644 index 0000000..3c74ec6 --- /dev/null +++ b/test/cve_corpus/cwe682/cve_2018_20999_cwe682_orion_notprevented.cpp @@ -0,0 +1,66 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// =========================================================================== +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2018-20999 +// cwe: CWE-682 +// product: orion crate (Rust) +// version: before 0.11.2 +// summary: Incorrect reset() calculation in the orion crate. +// root-cause: an index computed one too large; the arithmetic stays in range +// root-cause-width: u32 +// trigger: base=100, length=50 +// consequence: one element out of bounds that the library cannot detect +// classification: NOT_PREVENTED +// expected-exception: none +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2018-20999 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-682&resultsPerPage=200&startIndex=0 +// notes: In-range calculation error the library cannot detect. +// BOOST_SAFE_NUMBERS_CVE_END +// =========================================================================== + +#include +#include + +#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE +import boost.safe_numbers; +#else +#include +#endif + +#include + +using namespace boost::safe_numbers; + +void native_reproduction() +{ + const std::uint32_t base {100U}; + const std::uint32_t length {50U}; + const std::uint32_t end_index {base + length}; + const std::uint32_t correct_index {base + length - 1U}; + + BOOST_TEST_EQ(end_index, 150U); + BOOST_TEST(end_index != correct_index); +} + +void safe_reproduction() +{ + const u32 base {100U}; + const u32 length {50U}; + + BOOST_TEST_NO_THROW((void)(base + length)); + const u32 end_index {base + length}; + BOOST_TEST_EQ(static_cast(end_index), 150U); +} + +int main() +{ + native_reproduction(); + safe_reproduction(); + return boost::report_errors(); +} From 0a8a7289963f488932c4b7cc419e4dbde4466699 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Aug 2026 14:16:05 -0400 Subject: [PATCH 2/5] Add corpus aggregation file --- test/cve_corpus/analysis/aggregate.py | 365 ++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 test/cve_corpus/analysis/aggregate.py diff --git a/test/cve_corpus/analysis/aggregate.py b/test/cve_corpus/analysis/aggregate.py new file mode 100644 index 0000000..4c7c881 --- /dev/null +++ b/test/cve_corpus/analysis/aggregate.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 +# Copyright 2026 Matt Borland +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +# +# Aggregate the safe_numbers CVE corpus into per-CWE prevention statistics. +# Pure standard library only (no third party dependencies). +# +# It walks the corpus tree, parses the machine readable metadata block at the top +# of each .cpp file, reads the out_of_scope.csv manifest, optionally cross checks a +# results file that says whether each test actually demonstrated its behavior, and +# emits: corpus.csv (auditable manifest), results_by_cwe.csv (the per-CWE table), +# and results.adoc (a rendered results section for the manual). +# +# Usage: +# python3 aggregate.py [--corpus-root DIR] [--out-dir DIR] [--results PATH|none] +# +# The results file, when given, is a TSV of "stemPASS|FAIL" where stem is the +# file basename without extension. A prevented entry whose test did not pass is +# flagged and is NOT counted as prevented. Exit status is nonzero on any schema or +# consistency error so a CI job can gate the corpus. + +import argparse +import csv +import glob +import math +import os +import re +import sys + +CATEGORIES = ["CWE-190", "CWE-191", "CWE-681", "CWE-369", "CWE-682"] +CATEGORY_TITLES = { + "CWE-190": "Integer Overflow or Wraparound", + "CWE-191": "Integer Underflow", + "CWE-681": "Incorrect Conversion between Numeric Types", + "CWE-369": "Divide By Zero", + "CWE-682": "Incorrect Calculation (negative control)", +} +ALL_CLASSES = { + "PREVENTED_RUNTIME", "PREVENTED_COMPILETIME", "PREVENTED_BOUNDED", + "NOT_PREVENTED", "OUT_OF_SCOPE", +} +PREVENTED = {"PREVENTED_RUNTIME", "PREVENTED_COMPILETIME", "PREVENTED_BOUNDED"} +PREVENTED_DEFAULT = {"PREVENTED_RUNTIME", "PREVENTED_COMPILETIME"} +EXCEPTIONS = {"std::overflow_error", "std::underflow_error", "std::domain_error", "none"} +NONE_EXC_CLASSES = {"PREVENTED_COMPILETIME", "NOT_PREVENTED", "OUT_OF_SCOPE"} + +BEGIN = "BOOST_SAFE_NUMBERS_CVE_BEGIN" +END = "BOOST_SAFE_NUMBERS_CVE_END" +REQUIRED = ["cve-id", "cwe", "classification", "expected-exception", "tier-form"] +Z95 = 1.959963984540054 + + +def wilson(k, n, z=Z95): + # Wilson score interval for a binomial proportion. Wald is unusable here because + # it degenerates to zero width at k == n, exactly the near ceiling regime we expect. + if n == 0: + return (float("nan"), float("nan")) + p = k / n + z2 = z * z + denom = 1.0 + z2 / n + center = (p + z2 / (2.0 * n)) / denom + margin = (z / denom) * math.sqrt((p * (1.0 - p) + z2 / (4.0 * n)) / n) + return (max(0.0, center - margin), min(1.0, center + margin)) + + +def mcnemar_two_sided(b, n10=0): + # Native baseline detects 0 by construction, so n10 == 0 and every prevented case + # is a discordant pair favoring safe_numbers. This is the exact McNemar test + # reduced to a binomial tail. It is ceilinged by design: it certifies the + # asymmetry is not chance, not the size of the effect. + d = b + n10 + if d == 0: + return 1.0 + m = min(b, n10) + tail = sum(math.comb(d, k) for k in range(0, m + 1)) * (0.5 ** d) + return min(1.0, 2.0 * tail) + + +def fail(msg): + print("ERROR: " + msg, file=sys.stderr) + sys.exit(2) + + +def parse_block(path): + with open(path, "r") as f: + text = f.read() + if BEGIN not in text or END not in text: + fail("missing metadata block in " + path) + body = text.split(BEGIN, 1)[1].split(END, 1)[0] + rec = {"cwe": [], "reference": [], "notes": []} + for raw in body.splitlines(): + line = raw.strip() + if line.startswith("//"): + line = line[2:].strip() + if not line or ":" not in line: + continue + key, val = line.split(":", 1) + key = key.strip() + val = val.strip() + if key == "cwe": + rec["cwe"] = [c.strip() for c in val.split(",") if c.strip()] + elif key in ("reference", "notes"): + rec[key].append(val) + else: + rec[key] = val + return rec + + +def category_from_name(stem): + m = re.search(r"cwe(\d+)", stem) + return ("CWE-" + m.group(1)) if m else None + + +def validate(rec, stem, path): + for k in REQUIRED: + if k not in rec or (isinstance(rec[k], str) and not rec[k]): + fail("%s: missing required key '%s'" % (path, k)) + cls = rec["classification"] + if cls not in ALL_CLASSES: + fail("%s: bad classification '%s'" % (path, cls)) + exc = rec["expected-exception"] + if exc not in EXCEPTIONS: + fail("%s: bad expected-exception '%s'" % (path, exc)) + if cls in NONE_EXC_CLASSES and exc != "none": + fail("%s: classification %s must have expected-exception none" % (path, cls)) + if cls not in NONE_EXC_CLASSES and exc == "none": + fail("%s: classification %s must name an exception" % (path, cls)) + cat = category_from_name(stem) + if cat is None: + fail("%s: filename does not encode a cweNNN category" % path) + if cat not in rec["cwe"]: + fail("%s: filename category %s is not in the cwe tags %s" % (path, cat, rec["cwe"])) + tier = rec["tier-form"] + if cls == "PREVENTED_COMPILETIME" and tier != "compile-fail": + fail("%s: PREVENTED_COMPILETIME must be tier-form compile-fail" % path) + if cls in ("PREVENTED_RUNTIME", "PREVENTED_BOUNDED", "NOT_PREVENTED") and tier != "run": + fail("%s: %s must be tier-form run" % (path, cls)) + return cat + + +def load_results(path): + if not path or path == "none": + return None + status = {} + with open(path, "r") as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + parts = line.split("\t") if "\t" in line else line.split() + if len(parts) >= 2: + status[parts[0]] = parts[1].upper() + return status + + +def fmt_pct(x): + return "%.1f%%" % (100.0 * x) if x == x else "n/a" + + +def main(): + ap = argparse.ArgumentParser() + here = os.path.dirname(os.path.abspath(__file__)) + ap.add_argument("--corpus-root", default=os.path.dirname(here)) + ap.add_argument("--out-dir", default=here) + ap.add_argument("--results", default="none") + ap.add_argument("--partial-out", default=os.path.normpath(os.path.join( + os.path.dirname(here), "..", "..", "doc", "modules", "ROOT", "partials", "cve_results.adoc"))) + args = ap.parse_args() + + results = load_results(args.results) + + rows = [] + for path in sorted(glob.glob(os.path.join(args.corpus_root, "**", "*.cpp"), recursive=True)): + stem = os.path.splitext(os.path.basename(path))[0] + rec = parse_block(path) + cat = validate(rec, stem, path) + cls = rec["classification"] + demonstrated = "unverified" + counts_prevented = cls in PREVENTED + if results is not None: + st = results.get(stem) + if st is None: + demonstrated = "missing" + else: + demonstrated = st + if st != "PASS" and counts_prevented: + print("WARNING: %s is %s but its test did not PASS; not counted as prevented" + % (stem, cls), file=sys.stderr) + counts_prevented = False + rows.append({ + "cve": rec.get("cve-id", ""), + "category": cat, + "cwe_tags": ";".join(rec["cwe"]), + "product": rec.get("product", ""), + "classification": cls, + "counts_prevented": counts_prevented, + "operation": rec.get("root-cause", ""), + "width": rec.get("root-cause-width", ""), + "expected_exception": rec["expected-exception"], + "tier_form": rec["tier-form"], + "nvd_url": (rec["reference"][0] if rec["reference"] else ""), + "demonstrated": demonstrated, + "stem": stem, + }) + + # Out of scope manifest. + oos_rows = [] + oos_path = os.path.join(here, "out_of_scope.csv") + if os.path.exists(oos_path): + with open(oos_path, "r") as f: + for r in csv.DictReader(f): + oos_rows.append(r) + + if not rows: + fail("no corpus files found under " + args.corpus_root) + + # Per category aggregation. + per = {} + for cat in CATEGORIES: + crows = [r for r in rows if r["category"] == cat] + n_prevented = sum(1 for r in crows if r["counts_prevented"]) + n_prevented_default = sum( + 1 for r in crows if r["counts_prevented"] and r["classification"] in PREVENTED_DEFAULT) + n_not_prev = sum(1 for r in crows if r["classification"] == "NOT_PREVENTED") + n_oos = sum(1 for r in oos_rows if r["category"] == cat) + \ + sum(1 for r in crows if r["classification"] == "OUT_OF_SCOPE") + n_in_scope = n_prevented + n_not_prev + n_total = n_in_scope + n_oos + rate = (n_prevented / n_in_scope) if n_in_scope else float("nan") + drate = (n_prevented_default / n_in_scope) if n_in_scope else float("nan") + lo, hi = wilson(n_prevented, n_in_scope) + per[cat] = { + "n_total": n_total, "n_oos": n_oos, "n_in_scope": n_in_scope, + "n_prevented": n_prevented, "n_prevented_default": n_prevented_default, + "n_not_prevented": n_not_prev, "rate": rate, "default_rate": drate, + "wilson_lo": lo, "wilson_hi": hi, "mcnemar_p": mcnemar_two_sided(n_prevented), + } + + # Pooled and category averaged. + pooled_prev = sum(per[c]["n_prevented"] for c in CATEGORIES) + pooled_prev_default = sum(per[c]["n_prevented_default"] for c in CATEGORIES) + pooled_in = sum(per[c]["n_in_scope"] for c in CATEGORIES) + pooled_rate = (pooled_prev / pooled_in) if pooled_in else float("nan") + pooled_lo, pooled_hi = wilson(pooled_prev, pooled_in) + valid_cats = [c for c in CATEGORIES if per[c]["n_in_scope"] > 0] + cat_avg = (sum(per[c]["rate"] for c in valid_cats) / len(valid_cats)) if valid_cats else float("nan") + + # Emit corpus.csv. + corpus_csv = os.path.join(args.out_dir, "corpus.csv") + with open(corpus_csv, "w", newline="") as f: + w = csv.writer(f) + w.writerow(["cve", "category", "cwe_tags", "product", "classification", + "counts_prevented", "operation", "width", "expected_exception", + "tier_form", "demonstrated", "nvd_url", "stem"]) + for r in sorted(rows, key=lambda x: (x["category"], x["cve"])): + w.writerow([r["cve"], r["category"], r["cwe_tags"], r["product"], + r["classification"], r["counts_prevented"], r["operation"], + r["width"], r["expected_exception"], r["tier_form"], + r["demonstrated"], r["nvd_url"], r["stem"]]) + for r in oos_rows: + w.writerow([r["cve"], r["category"], "", "", "OUT_OF_SCOPE", False, + "", "", "none", "excluded", "unverified", r.get("nvd_url", ""), ""]) + + # Emit results_by_cwe.csv. + by_cwe_csv = os.path.join(args.out_dir, "results_by_cwe.csv") + with open(by_cwe_csv, "w", newline="") as f: + w = csv.writer(f) + w.writerow(["category", "title", "n_total", "n_out_of_scope", "n_in_scope", + "n_prevented", "n_prevented_default", "n_not_prevented", + "prevention_rate", "wilson_lo", "wilson_hi", "prevented_default_rate", + "mcnemar_two_sided_p"]) + for c in CATEGORIES: + d = per[c] + w.writerow([c, CATEGORY_TITLES[c], d["n_total"], d["n_oos"], d["n_in_scope"], + d["n_prevented"], d["n_prevented_default"], d["n_not_prevented"], + "%.4f" % d["rate"] if d["rate"] == d["rate"] else "nan", + "%.4f" % d["wilson_lo"] if d["wilson_lo"] == d["wilson_lo"] else "nan", + "%.4f" % d["wilson_hi"] if d["wilson_hi"] == d["wilson_hi"] else "nan", + "%.4f" % d["default_rate"] if d["default_rate"] == d["default_rate"] else "nan", + "%.3g" % d["mcnemar_p"]]) + w.writerow(["POOLED", "All categories", pooled_in + sum(per[c]["n_oos"] for c in CATEGORIES), + sum(per[c]["n_oos"] for c in CATEGORIES), pooled_in, pooled_prev, "", "", + "%.4f" % pooled_rate if pooled_rate == pooled_rate else "nan", + "%.4f" % pooled_lo, "%.4f" % pooled_hi, "", + "%.3g" % mcnemar_two_sided(pooled_prev)]) + + # Emit results.adoc. + adoc = os.path.join(args.out_dir, "results.adoc") + with open(adoc, "w") as f: + f.write("// Generated by aggregate.py. Do not edit by hand.\n") + f.write("= CVE corpus results\n\n") + f.write("This section is generated from the corpus metadata by ") + f.write("`test/cve_corpus/analysis/aggregate.py`.\n\n") + f.write("== Disposition funnel\n\n") + total_drawn = sum(per[c]["n_total"] for c in CATEGORIES) + total_oos = sum(per[c]["n_oos"] for c in CATEGORIES) + f.write("[cols=\"1,1,1,1,1,1\",options=\"header\"]\n|===\n") + f.write("|Category |Examined |Out of scope |In scope |Prevented |Not prevented\n") + for c in CATEGORIES: + d = per[c] + f.write("|%s |%d |%d |%d |%d |%d\n" % ( + c, d["n_total"], d["n_oos"], d["n_in_scope"], d["n_prevented"], d["n_not_prevented"])) + f.write("|All |%d |%d |%d |%d |%d\n" % ( + total_drawn, total_oos, pooled_in, pooled_prev, pooled_in - pooled_prev)) + f.write("|===\n\n") + f.write("== Prevention rate by category\n\n") + f.write("The \"by default\" column counts detection with the default checked types alone; ") + f.write("the \"incl. bounded\" column adds cases prevented once a value's domain is expressed ") + f.write("with a bounded type.\n\n") + f.write("[cols=\"1,3,1,1,1,1,1\",options=\"header\"]\n|===\n") + f.write("|CWE |Weakness |In scope |Prevented by default |Prevented incl. bounded " + "|Prevention rate (95% Wilson CI) |McNemar p\n") + for c in CATEGORIES: + d = per[c] + ci = "%s (%s to %s)" % (fmt_pct(d["rate"]), fmt_pct(d["wilson_lo"]), fmt_pct(d["wilson_hi"])) + f.write("|%s |%s |%d |%d |%d |%s |%.3g\n" % ( + c, CATEGORY_TITLES[c], d["n_in_scope"], d["n_prevented_default"], d["n_prevented"], + ci, d["mcnemar_p"])) + pci = "%s (%s to %s)" % (fmt_pct(pooled_rate), fmt_pct(pooled_lo), fmt_pct(pooled_hi)) + f.write("|POOLED |All categories |%d |%d |%d |%s |%.3g\n" % ( + pooled_in, pooled_prev_default, pooled_prev, pci, mcnemar_two_sided(pooled_prev))) + f.write("|===\n\n") + f.write("Category averaged prevention rate (unweighted mean of the per category rates): %s.\n\n" + % fmt_pct(cat_avg)) + f.write("== Reading these numbers\n\n") + f.write("The native baseline detects zero of these faults by construction, since each CVE ") + f.write("shipped in native integer code. Every prevented case is therefore a discordant pair ") + f.write("favoring safe_numbers, so the McNemar p value is ceilinged by design: it certifies ") + f.write("that the asymmetry is not chance, and it is not an effect size. The prevention rate ") + f.write("and its Wilson interval are the primary result, bounded by the genuine failure mode ") + f.write("visible in the not prevented cases.\n\n") + f.write("In the CWE-682 negative control the gap between the two prevented columns is the ") + f.write("contribution of bounded types: calculation errors whose wrong result is used as an ") + f.write("index, offset, or length into a buffer of known size are caught when that domain is ") + f.write("declared with a bounded type, even though the arithmetic itself does not overflow. ") + f.write("The cases that remain not prevented are in range value errors (rounding, a wrong ") + f.write("cryptographic result, a floating point mishandling) where no bound applies.\n") + + # Also emit the results as an Antora partial so the manual page stays in sync. + wrote_partial = None + doc_root = os.path.dirname(os.path.dirname(args.partial_out)) # .../ROOT + if os.path.isdir(doc_root): + os.makedirs(os.path.dirname(args.partial_out), exist_ok=True) + with open(adoc, "r") as src, open(args.partial_out, "w") as dst: + dst.write(src.read()) + wrote_partial = args.partial_out + + # Console summary. + print("Parsed %d corpus files, %d out of scope manifest rows." % (len(rows), len(oos_rows))) + for c in CATEGORIES: + d = per[c] + print(" %-8s in_scope=%2d prevented=%2d rate=%s CI=[%s,%s] p=%.3g" % ( + c, d["n_in_scope"], d["n_prevented"], fmt_pct(d["rate"]), + fmt_pct(d["wilson_lo"]), fmt_pct(d["wilson_hi"]), d["mcnemar_p"])) + print(" POOLED in_scope=%2d prevented=%2d rate=%s CI=[%s,%s] p=%.3g" % ( + pooled_in, pooled_prev, fmt_pct(pooled_rate), fmt_pct(pooled_lo), fmt_pct(pooled_hi), + mcnemar_two_sided(pooled_prev))) + print("Wrote:\n %s\n %s\n %s" % (corpus_csv, by_cwe_csv, adoc)) + if wrote_partial: + print(" %s" % wrote_partial) + + +if __name__ == "__main__": + main() From eede26d5e367c8cca2cd58b41ead2a906203d709 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Aug 2026 14:16:14 -0400 Subject: [PATCH 3/5] Add results --- test/cve_corpus/README.adoc | 199 ++++++++++++++++++++ test/cve_corpus/analysis/corpus.csv | 141 ++++++++++++++ test/cve_corpus/analysis/out_of_scope.csv | 11 ++ test/cve_corpus/analysis/results.adoc | 40 ++++ test/cve_corpus/analysis/results_by_cwe.csv | 7 + 5 files changed, 398 insertions(+) create mode 100644 test/cve_corpus/README.adoc create mode 100644 test/cve_corpus/analysis/corpus.csv create mode 100644 test/cve_corpus/analysis/out_of_scope.csv create mode 100644 test/cve_corpus/analysis/results.adoc create mode 100644 test/cve_corpus/analysis/results_by_cwe.csv diff --git a/test/cve_corpus/README.adoc b/test/cve_corpus/README.adoc new file mode 100644 index 0000000..54e9954 --- /dev/null +++ b/test/cve_corpus/README.adoc @@ -0,0 +1,199 @@ += boost.safe_numbers CVE corpus +:toc: left +:idprefix: cve_ + +An empirical corpus that measures how often adopting `boost::safe_numbers` would have +converted the arithmetic fault at the root of a real, publicly disclosed CVE into a +detected, controlled failure. It complements the Why3 verification: the proofs establish +that the checked operations are correct for all inputs (soundness), while this corpus +estimates how often that mechanism, had it been adopted, would have engaged on real +historical faults (coverage and relevance). + +== The claim, stated carefully + +We reproduce the arithmetic fault. We do not re run the original programs. For each in +scope CVE we extract the specific integer computation that the public disclosure and its +patch identify as the root cause, and we show under identical inputs that: + +. the native fixed width computation silently produces the same incorrect value the + disclosure attributes the vulnerability to, and +. the identical computation written with `boost::safe_numbers` halts at the faulting + operation with a typed, catchable fault (a thrown exception at runtime, or a build error). + +We do not claim the entire original program would have been immune. The library acts at the +arithmetic root, upstream of the downstream memory safety consequence. + +== Layout + +[source] +---- +test/cve_corpus/ + README.adoc this file + cve_corpus_util.hpp warning clean ground truth widening helpers + cve___cwe__.cpp run tests + compile_fail_cve___cwe__.cpp compile-fail tests + analysis/ + aggregate.py pure stdlib parser, statistics, report generator + out_of_scope.csv examined CVEs judged out of scope, with reasons + corpus.csv generated: one row per CVE (auditable manifest) + results_by_cwe.csv generated: the per-CWE table + results.adoc generated: the rendered results section +---- + +Each file counts under the CWE encoded in its name (`cwe`), which must be one of the +NVD CWE tags recorded in its metadata. Basenames embed the CVE id so they are globally +unique across the test tree. + +== File structure + +Every entry carries a machine readable metadata block delimited by +`BOOST_SAFE_NUMBERS_CVE_BEGIN` and `BOOST_SAFE_NUMBERS_CVE_END`, one `key: value` per line: + +[source,cpp] +---- +// BOOST_SAFE_NUMBERS_CVE_BEGIN +// cve-id: CVE-2002-0639 +// cwe: CWE-190 +// product: OpenSSH +// version: 2.9.9 through 3.3 +// summary: Integer overflow in sshd challenge-response auth allows RCE. +// root-cause: unsigned multiplication (nresp * sizeof(char*)) +// root-cause-width: u32 +// trigger: nresp=1073741824, element_size=4 +// consequence: heap buffer overflow +// classification: PREVENTED_RUNTIME +// expected-exception: std::overflow_error +// tier-form: run +// reference: https://nvd.nist.gov/vuln/detail/CVE-2002-0639 +// nvd-cwe-source: primary +// sampled-on: 2026-08-19 +// sample-query: cweId=CWE-190&resultsPerPage=200&startIndex=0 +// notes: modeling notes and fidelity caveats +// BOOST_SAFE_NUMBERS_CVE_END +---- + +A run test has a `native_reproduction()` that computes the vulnerable expression with +builtin fixed width types and asserts the silent wrong value deterministically (the true +value is computed in a wider type from `cve_corpus_util.hpp`), plus a `safe_reproduction()` +that computes the identical expression with the library types and asserts the fault with +`BOOST_TEST_THROWS`. Both arms use `boost::core` lightweight_test and `main` returns +`boost::report_errors()`. + +== Classifications + +[cols="1,4",options="header"] +|=== +|Classification |Meaning +|`PREVENTED_RUNTIME` |the safe computation throws at the faulting operation +|`PREVENTED_COMPILETIME` |porting to safe types makes the expression ill formed (mixed width, mixed signedness, implicit builtin conversion, bool construction, or a constexpr overflow); a `compile-fail` test +|`PREVENTED_BOUNDED` |the value domain is expressed with a bounded type that rejects the out of domain input at construction +|`NOT_PREVENTED` |a genuine integer arithmetic CVE whose faulting value is representable and in range, so the library cannot detect it; counts in the denominator +|`OUT_OF_SCOPE` |on reduction, not a fixed width integer arithmetic fault; recorded in `analysis/out_of_scope.csv`, removed from the denominator +|=== + +== Bounded types and the CWE-682 control + +A calculation error whose arithmetic does not overflow is invisible to the default checked +types: the operation is representable, so nothing fires. But when the wrong result is used +as an index, offset, or length into a buffer of independently known size, declaring that +domain with a bounded type turns the fault into a caught `std::domain_error` at the point +the value is formed. For example, an off-by-one index of 150 into a 150-element buffer is +rejected by `bounded_uint<0, 149>` even though the addition 100 + 50 is perfectly correct +arithmetic. Three of the CWE-682 control cases (an off-by-one index, an over long SCTP +length, and an out-of-bounds file offset) are prevented this way and are classified +`PREVENTED_BOUNDED`; the control's prevented count rises from three (by default) to six once +domains are declared. The bound must come from an independent quantity (the real buffer +size), never from the correct answer. The remaining four control cases stay `NOT_PREVENTED` +because their wrong result is in range: a rounded time value, a wrong cryptographic result, +a mishandled floating point value, and a wrong cipher-reset output. No bound applies to +these, which is exactly why the negative control still demonstrates the library's limits. + +== Sampling protocol (anti cherry pick) + +. Enumerate CVEs from the NVD REST API 2.0 by CWE, for example + `https://services.nvd.nist.gov/rest/json/cves/2.0?cweId=CWE-190`. Because we sample by + CWE, every entry sits in a category the NVD itself assigned, not one we reassigned. +. Record the query, the retrieval date, and the disposition of every examined CVE. Nothing + is silently dropped: an examined CVE is either in scope (one of the prevented classes or + `NOT_PREVENTED`) or `OUT_OF_SCOPE` with a recorded reason. +. `NOT_PREVENTED` counts in the in scope denominator. `OUT_OF_SCOPE` is reported separately + in the disposition funnel, so a high out of scope rate is visible rather than hidden. +. CWE-682 (Incorrect Calculation) is included as a negative control, a category where we + expect a distinctly lower prevention rate because many of its defects are logic errors + the library cannot catch. A study that also measures where the library does not help is + a measurement, not an advertisement. + +Reproduction fidelity: we port only the operation the patch cites, with the disclosed +operand widths and a triggering input, and we assert the specific wrong value the +disclosure describes, not merely some wrong value. Where the original was C and mixed +platform dependent widths (`int`, `size_t`, `long`), we model the width the advisory +assumes and record it in `root-cause-width`, which makes the reproduction deterministic and +architecture independent. + +Purposive sample, not a random draw: the current corpus is CURATED. From the NVD by-CWE +pools we selected CVEs whose arithmetic root cause is reducible to a self contained snippet, +so the primary-category prevention rate should be read as conditional on that reducibility, +"among CVEs whose root cause reduces to a fixed-width integer arithmetic fault," not "among +all CVEs tagged with the CWE." The `out_of_scope.csv` entries illustrate the exclusion +category (they are concentrated in CWE-682, the noisiest category) but are not a complete +random-sample funnel. The credibility of the result rests on the CWE-682 negative control +(where the mechanism demonstrably does not fire on in-range logic errors) and on the honest +`NOT_PREVENTED` cases, not on a claim of random sampling. Converting this to a fully random +draw with complete classification of every drawn id is the natural next step. + +== Statistics + +The primary metric per category is the prevention rate, prevented divided by in scope, +reported with a 95% Wilson score confidence interval (Wilson, not Wald, because Wald +degenerates to zero width at a perfect observed rate, exactly the regime here). We also +report the stricter prevented by default rate that excludes `PREVENTED_BOUNDED`. + +The native baseline detects zero faults by construction, since every CVE shipped in native +integer code. Every prevented case is therefore a discordant pair favoring safe_numbers, so +the exact McNemar test reduces to a binomial tail, two sided p = min(1, 2 * 0.5^b) for b +prevented. This p is ceilinged by design: it certifies the asymmetry is not chance, and it +is not an effect size. Foreground the prevention rate and its interval, which are bounded by +the real failure mode in the not prevented cases and the negative control. + +== Threats to validity + +* Reproduction fidelity: we reduce a CVE to its arithmetic; port only the patched + expression, with disclosed widths and trigger, and assert the specific disclosed wrong + value. +* Construct validity: a thrown exception converts silent memory corruption into a + controlled, localized, typed failure at the faulting operation. That is the intended and + strictly superior trade, and the library also offers non throwing facilities + (`checked_*` returning `std::optional`) for builds that cannot use exceptions. +* Selection bias: sampling is by NVD CWE with recorded provenance, every examined CVE is + classified, the out of scope funnel is reported, and a negative control is included. +* Small n: report Wilson intervals, never a bare point estimate. +* External validity: the counterfactual concerns the arithmetic root in isolation, not the + whole program, and the results transfer to new code adopting the library at the + arithmetic site rather than to arbitrary vulnerability classes. + +== Building and reproducing + +[source,bash] +---- +# build and run the corpus with the rest of the test suite +b2 libs/safe_numbers/test + +# regenerate corpus.csv, results_by_cwe.csv, results.adoc and the doc partial +python3 test/cve_corpus/analysis/aggregate.py + +# optionally cross check against test outcomes: pass a TSV of "stemPASS|FAIL" +python3 test/cve_corpus/analysis/aggregate.py --results results.tsv +---- + +`aggregate.py` validates every metadata block and exits nonzero on any schema or +consistency error, so the corpus can be gated in continuous integration. + +== Extending the corpus + +Add one `.cpp` per CVE under the appropriate `cwe/` subdirectory following the +templates and the metadata schema, add a `run` or `compile-fail` line to `../Jamfile`, and +re run `aggregate.py`. The corpus is at the robust tier: thirty in scope CVEs per primary +category (CWE-190, CWE-191, CWE-681, CWE-369) plus a smaller CWE-682 negative control. At +that size each primary category clears per category significance and its 95% Wilson lower +bound sits near ninety percent. The schema, the analysis, and the Jamfile pattern scale +further without change. diff --git a/test/cve_corpus/analysis/corpus.csv b/test/cve_corpus/analysis/corpus.csv new file mode 100644 index 0000000..2658574 --- /dev/null +++ b/test/cve_corpus/analysis/corpus.csv @@ -0,0 +1,141 @@ +cve,category,cwe_tags,product,classification,counts_prevented,operation,width,expected_exception,tier_form,demonstrated,nvd_url,stem +CVE-2002-0391,CWE-190,CWE-190,SunRPC xdr_array (glibc),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2002-0391,cve_2002_0391_cwe190_sunrpc_xdrarray_mul +CVE-2002-0639,CWE-190,CWE-190,OpenSSH,PREVENTED_RUNTIME,True,unsigned multiplication (nresp * sizeof(char*)) in the response array size,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2002-0639,cve_2002_0639_cwe190_openssh_challenge_mul +CVE-2004-0657,CWE-190,CWE-190,NTP daemon (ntpd),PREVENTED_RUNTIME,True,unsigned addition of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2004-0657,cve_2004_0657_cwe190_ntpd_offset_add +CVE-2004-0788,CWE-190,CWE-190,gdk-pixbuf ICO decoder,PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2004-0788,cve_2004_0788_cwe190_gdkpixbuf_ico_mul +CVE-2004-2013,CWE-190,CWE-190,Linux kernel SCTP (SCTP_SOCKOPT_DEBUG_NAME),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2004-2013,cve_2004_2013_cwe190_kernel_sctp_debug_mul +CVE-2005-0102,CWE-190,CWE-190,Evolution (camel-lock-helper),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2005-0102,cve_2005_0102_cwe190_evolution_camel_mul +CVE-2005-1141,CWE-190,CWE-190,GOCR (readpgm in pnm.c),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2005-1141,cve_2005_1141_cwe190_gocr_pnm_mul +CVE-2005-1513,CWE-190,CWE-190,"qmail (stralloc_readyplus, 64-bit)",PREVENTED_RUNTIME,True,unsigned addition of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2005-1513,cve_2005_1513_cwe190_qmail_stralloc_add +CVE-2005-2976,CWE-190,CWE-190,GTK+ gdk-pixbuf (io-xpm.c),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2005-2976,cve_2005_2976_cwe190_gtk_xpm_mul +CVE-2006-3198,CWE-190,CWE-190,Opera (JPEG handling),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2006-3198,cve_2006_3198_cwe190_opera_jpeg_mul +CVE-2006-4519,CWE-190,CWE-190,GIMP image loader plugins (DICOM),PREVENTED_RUNTIME,True,unsigned multiplication (width * height) of image dimensions,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2006-4519,cve_2006_4519_cwe190_gimp_dicom_mul +CVE-2007-0221,CWE-190,CWE-190,Microsoft Exchange (IMAP),PREVENTED_RUNTIME,True,unsigned addition of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2007-0221,cve_2007_0221_cwe190_exchange_imap_add +CVE-2007-2834,CWE-190,CWE-190,OpenOffice.org TIFF parser,PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2007-2834,cve_2007_2834_cwe190_ooo_tiff_mul +CVE-2007-2949,CWE-190,CWE-190,GIMP PSD plugin,PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2007-2949,cve_2007_2949_cwe190_gimp_psd_mul +CVE-2007-3387,CWE-190,CWE-190,xpdf StreamPredictor,PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2007-3387,cve_2007_3387_cwe190_xpdf_predictor_mul +CVE-2007-4965,CWE-190,CWE-190,Python (imageop module),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2007-4965,cve_2007_4965_cwe190_python_imageop_mul +CVE-2007-6353,CWE-190,CWE-190,Exiv2 (exif.cpp),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2007-6353,cve_2007_6353_cwe190_exiv2_exif_mul +CVE-2008-1374,CWE-190,CWE-190,CUPS pdftops filter (64-bit),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2008-1374,cve_2008_1374_cwe190_cups_pdftops_mul +CVE-2008-2663,CWE-190,CWE-190,Ruby (rb_ary_store),PREVENTED_RUNTIME,True,unsigned multiplication (capacity * element_size) for an array buffer,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2008-2663,cve_2008_2663_cwe190_ruby_ary_store_mul +CVE-2008-2826,CWE-190,CWE-190,Linux kernel SCTP (getsockopt_local_addrs),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2008-2826,cve_2008_2826_cwe190_kernel_sctp_addrs_mul +CVE-2008-4019,CWE-190,CWE-190,Microsoft Excel (REPT),PREVENTED_RUNTIME,True,unsigned multiplication of two values,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2008-4019,cve_2008_4019_cwe190_excel_rept_mul +CVE-2009-0723,CWE-190,CWE-190,LittleCMS (lcms / liblcms),PREVENTED_RUNTIME,True,unsigned multiplication (entry_count * element_size) for a table allocation,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2009-0723,cve_2009_0723_cwe190_lcms_mul +CVE-2009-0946,CWE-190,CWE-190,FreeType (smooth rasterizer),PREVENTED_RUNTIME,True,unsigned multiplication (width * rows) of glyph bitmap dimensions,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2009-0946,cve_2009_0946_cwe190_freetype_smooth_mul +CVE-2010-3442,CWE-190,CWE-190,Linux kernel ALSA (snd_ctl_new),PREVENTED_RUNTIME,True,unsigned multiplication (count * element_size) for a control array,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2010-3442,cve_2010_3442_cwe190_kernel_alsa_mul +CVE-2011-1178,CWE-190,CWE-190,GIMP PCX plugin (load_image in file-pcx.c),PREVENTED_RUNTIME,True,unsigned multiplication (width * height) of PCX dimensions,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2011-1178,cve_2011_1178_cwe190_gimp_pcx_mul +CVE-2012-1185,CWE-190,CWE-190,ImageMagick (magick/profile.c),PREVENTED_RUNTIME,True,unsigned addition (existing_length + added_length) of profile sizes,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2012-1185,cve_2012_1185_cwe190_imagemagick_profile_add +CVE-2013-7437,CWE-190,CWE-190,potrace,PREVENTED_RUNTIME,True,unsigned multiplication (width * height) of BMP image dimensions,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2013-7437,cve_2013_7437_cwe190_potrace_bmp_mul +CVE-2014-4608,CWE-190,CWE-190,Linux kernel LZO decompressor (lzo1x_decompress_safe),PREVENTED_RUNTIME,True,unsigned addition (output_position + run_length) overflows the 32-bit accumulator,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2014-4608,cve_2014_4608_cwe190_kernel_lzo_add +CVE-2015-1283,CWE-190,CWE-190,Expat (libexpat),PREVENTED_RUNTIME,True,signed addition (len + keep) of two int buffer sizes overflows INT_MAX,i32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-1283,cve_2015_1283_cwe190_expat_getbuffer_add +CVE-2018-13785,CWE-190,CWE-190;CWE-369,libpng,PREVENTED_BOUNDED,True,an oversized image width is used without enforcing the documented width limit,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-13785,cve_2018_13785_cwe190_libpng_width_bounded +CVE-2004-0184,CWE-191,CWE-191,tcpdump (isakmp_id_print),PREVENTED_RUNTIME,True,unsigned subtraction (item_len - fixed_header) with item_len too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2004-0184,cve_2004_0184_cwe191_tcpdump_isakmp_underflow +CVE-2004-0816,CWE-191,CWE-191,Linux iptables firewall logging,PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2004-0816,cve_2004_0816_cwe191_iptables_underflow +CVE-2004-1002,CWE-191,CWE-191,pppd (cbcp.c in ppp),PREVENTED_RUNTIME,True,unsigned subtraction (packet_length - fixed_header),u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2004-1002,cve_2004_1002_cwe191_pppd_cbcp_underflow +CVE-2005-0199,CWE-191,CWE-191,ngIRCd (Lists_MakeMask in lists.c),PREVENTED_RUNTIME,True,unsigned subtraction (length - offset) with length too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2005-0199,cve_2005_0199_cwe191_ngircd_mask_underflow +CVE-2009-3301,CWE-191,CWE-191,OpenOffice.org (ww8par2.cxx),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2009-3301,cve_2009_3301_cwe191_ooo_ww8_underflow +CVE-2010-2497,CWE-191,CWE-191,FreeType (glyph handling),PREVENTED_RUNTIME,True,unsigned subtraction (count - consumed) with count too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2010-2497,cve_2010_2497_cwe191_freetype_glyph_underflow +CVE-2010-4164,CWE-191,CWE-191,Linux kernel X.25 (x25_parse_facilities),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2010-4164,cve_2010_4164_cwe191_kernel_x25_underflow +CVE-2010-4529,CWE-191,CWE-191,Linux kernel IrDA (irda_getsockopt),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2010-4529,cve_2010_4529_cwe191_kernel_irda_underflow +CVE-2011-1770,CWE-191,CWE-191,Linux kernel DCCP (dccp_parse_options),PREVENTED_RUNTIME,True,unsigned subtraction (option_length - fixed) with option_length too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2011-1770,cve_2011_1770_cwe191_kernel_dccp_underflow +CVE-2011-2497,CWE-191,CWE-191,Linux kernel Bluetooth L2CAP (l2cap_config_req),PREVENTED_RUNTIME,True,unsigned subtraction (command_len - option_header) with command_len too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2011-2497,cve_2011_2497_cwe191_kernel_l2cap_underflow +CVE-2011-4031,CWE-191,CWE-191,FFmpeg (asfrtp_parse_packet),PREVENTED_RUNTIME,True,unsigned subtraction (packet_size - header) with packet_size too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2011-4031,cve_2011_4031_cwe191_ffmpeg_asfrtp_underflow +CVE-2013-6424,CWE-191,CWE-191,X.Org (xTrapezoidValid in render/picture.h),PREVENTED_RUNTIME,True,unsigned subtraction (bottom - top) with bottom less than top,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2013-6424,cve_2013_6424_cwe191_xorg_trapezoid_underflow +CVE-2013-6425,CWE-191,CWE-191,Pixman (as used in X.Org server and cairo),PREVENTED_RUNTIME,True,unsigned subtraction (bottom - top) with bottom less than top,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2013-6425,cve_2013_6425_cwe191_pixman_trapezoid_underflow +CVE-2014-0497,CWE-191,CWE-191,Adobe Flash Player,PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2014-0497,cve_2014_0497_cwe191_flash_underflow +CVE-2014-8768,CWE-191,CWE-191,tcpdump (geonet_print),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2014-8768,cve_2014_8768_cwe191_tcpdump_geonet_underflow +CVE-2014-9087,CWE-191,CWE-191,Libksba (as used in GnuPG),PREVENTED_RUNTIME,True,unsigned subtraction (length - 1) with length zero wraps to a huge value,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2014-9087,cve_2014_9087_cwe191_libksba_oid_underflow +CVE-2015-0537,CWE-191,CWE-191,EMC RSA BSAFE (base64 decode),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-0537,cve_2015_0537_cwe191_rsa_bsafe_underflow +CVE-2015-1208,CWE-191,CWE-191,FFmpeg (mov_read_default),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-1208,cve_2015_1208_cwe191_ffmpeg_mov_underflow +CVE-2015-2311,CWE-191,CWE-191,Cap'n Proto,PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-2311,cve_2015_2311_cwe191_capnproto_underflow +CVE-2015-5212,CWE-191,CWE-191,LibreOffice / Apache OpenOffice,PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-5212,cve_2015_5212_cwe191_libreoffice_underflow +CVE-2016-10166,CWE-191,CWE-191,GD Graphics Library (gd_interpolation.c),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-10166,cve_2016_10166_cwe191_libgd_interp_underflow +CVE-2016-10268,CWE-191,CWE-191,LibTIFF (tools/tiffcp.c),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-10268,cve_2016_10268_cwe191_libtiff_tiffcp_underflow +CVE-2016-1925,CWE-191,CWE-191,lha (header.c),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-1925,cve_2016_1925_cwe191_lha_header_underflow +CVE-2016-7800,CWE-191,CWE-191,GraphicsMagick (coders/meta.c),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-7800,cve_2016_7800_cwe191_graphicsmagick_meta_underflow +CVE-2017-14496,CWE-191,CWE-191,dnsmasq (add_pseudoheader),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-14496,cve_2017_14496_cwe191_dnsmasq_underflow +CVE-2017-15874,CWE-191,CWE-191,BusyBox (decompress_unlzma.c),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-15874,cve_2017_15874_cwe191_busybox_unlzma_underflow +CVE-2017-6313,CWE-191,CWE-191,gdk-pixbuf (io-icns.c),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-6313,cve_2017_6313_cwe191_gdkpixbuf_icns_underflow +CVE-2017-8911,CWE-191,CWE-191,tnef (unicode_to_utf8),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-8911,cve_2017_8911_cwe191_tnef_underflow +CVE-2017-8924,CWE-191,CWE-191,Linux kernel USB serial (io_ti.c),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-8924,cve_2017_8924_cwe191_kernel_io_ti_underflow +CVE-2017-9214,CWE-191,CWE-191,Open vSwitch (queue config reply),PREVENTED_RUNTIME,True,unsigned subtraction with the minuend too small,u32,std::underflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-9214,cve_2017_9214_cwe191_openvswitch_underflow +CVE-2004-0804,CWE-369,CWE-369,LibTIFF (tif_dirread.c),PREVENTED_RUNTIME,True,division (value / field) with an attacker controlled zero field,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2004-0804,cve_2004_0804_cwe369_libtiff_dirread_divzero +CVE-2009-1887,CWE-369,CWE-369,net-snmp (snmp_agent.c),PREVENTED_RUNTIME,True,division (value / step) with an attacker controlled zero step,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2009-1887,cve_2009_1887_cwe369_netsnmp_divzero +CVE-2011-1012,CWE-369,CWE-369,Linux kernel LDM (ldm_parse_vmdb),PREVENTED_RUNTIME,True,modulo (offset % vblk_size) with a zero vblk_size,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2011-1012,cve_2011_1012_cwe369_kernel_ldm_modzero +CVE-2012-0207,CWE-369,CWE-369,Linux kernel IPv4 IGMP (igmp_heard_query),PREVENTED_RUNTIME,True,modulo (value % divisor) where a crafted query yields a zero divisor,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2012-0207,cve_2012_0207_cwe369_kernel_igmp_modzero +CVE-2014-9756,CWE-369,CWE-369,libsndfile (psf_fwrite),PREVENTED_RUNTIME,True,division (bytes_to_write / item_size) with an attacker controlled zero item size,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2014-9756,cve_2014_9756_cwe369_libsndfile_divzero +CVE-2015-3418,CWE-369,CWE-369,X.Org Server (ProcPutImage),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-3418,cve_2015_3418_cwe369_xorg_putimage_divzero +CVE-2015-6855,CWE-369,CWE-369,QEMU (hw/ide/core.c ATAPI),PREVENTED_RUNTIME,True,division (transfer / block_size) with a zero block size,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-6855,cve_2015_6855_cwe369_qemu_ide_divzero +CVE-2015-7513,CWE-369,CWE-369,Linux kernel KVM (x86.c PIT),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-7513,cve_2015_7513_cwe369_kernel_kvm_divzero +CVE-2016-10053,CWE-369,CWE-369,ImageMagick (coders/tiff.c),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-10053,cve_2016_10053_cwe369_imagemagick_tiff_divzero +CVE-2016-10219,CWE-369,CWE-369,Ghostscript (gxfill.c intersect),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-10219,cve_2016_10219_cwe369_ghostscript_intersect_divzero +CVE-2016-10266,CWE-369,CWE-369,LibTIFF (divide by zero),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-10266,cve_2016_10266_cwe369_libtiff_10266_divzero +CVE-2016-10267,CWE-369,CWE-369,LibTIFF (divide by zero),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-10267,cve_2016_10267_cwe369_libtiff_10267_divzero +CVE-2016-3622,CWE-369,CWE-369,LibTIFF (fpAcc in tif_predict.c),PREVENTED_RUNTIME,True,division (stride / bytes_per_sample) with a zero bytes per sample,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-3622,cve_2016_3622_cwe369_libtiff_predict_divzero +CVE-2016-3623,CWE-369,CWE-369,LibTIFF (rgb2ycbcr tool),PREVENTED_RUNTIME,True,division (dimension / subsampling) with an attacker controlled zero subsampling,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-3623,cve_2016_3623_cwe369_libtiff_rgb2ycbcr_divzero +CVE-2016-4797,CWE-369,CWE-369,OpenJPEG (tcd.c opj_tcd_init_tile),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-4797,cve_2016_4797_cwe369_openjpeg_tcd_divzero +CVE-2016-5323,CWE-369,CWE-369,LibTIFF (_TIFFFax3fillruns),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-5323,cve_2016_5323_cwe369_libtiff_fax3_divzero +CVE-2016-6505,CWE-369,CWE-369,Wireshark (packet-packetbb.c),PREVENTED_RUNTIME,True,division (value / count) with an attacker controlled zero count,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-6505,cve_2016_6505_cwe369_wireshark_packetbb_divzero +CVE-2016-7499,CWE-369,CWE-369,Libav (aacsbr.c),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-7499,cve_2016_7499_cwe369_libav_aacsbr_divzero +CVE-2016-8667,CWE-369,CWE-369,QEMU (rc4030),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-8667,cve_2016_8667_cwe369_qemu_rc4030_divzero +CVE-2016-8669,CWE-369,CWE-369,QEMU (serial_update_parameters),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-8669,cve_2016_8669_cwe369_qemu_serial_divzero +CVE-2016-8691,CWE-369,CWE-369,JasPer (jpc_dec_process_siz),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-8691,cve_2016_8691_cwe369_jasper_siz_divzero +CVE-2016-8697,CWE-369,CWE-369,potrace (bitmap.h bm_new),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-8697,cve_2016_8697_cwe369_potrace_bmnew_divzero +CVE-2016-9112,CWE-369,CWE-369,OpenJPEG (opj_pi_next_cprl in openjp2/pi.c),PREVENTED_RUNTIME,True,division by a zero step derived from crafted component parameters,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-9112,cve_2016_9112_cwe369_openjpeg_divzero +CVE-2016-9265,CWE-369,CWE-369,Libming (listmp3.c),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-9265,cve_2016_9265_cwe369_libming_mp3_divzero +CVE-2016-9922,CWE-369,CWE-369,QEMU (cirrus_do_copy),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-9922,cve_2016_9922_cwe369_qemu_cirrus_divzero +CVE-2017-6833,CWE-369,CWE-369,Audio File Library (BlockCodec runPull),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-6833,cve_2017_6833_cwe369_audiofile_runpull_divzero +CVE-2017-6835,CWE-369,CWE-369,Audio File Library (BlockCodec reset1),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-6835,cve_2017_6835_cwe369_audiofile_reset1_divzero +CVE-2017-7448,CWE-369,CWE-369,Dropbox Lepton (uncompressed_components.hh),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-7448,cve_2017_7448_cwe369_lepton_fb_divzero +CVE-2017-7595,CWE-369,CWE-369,LibTIFF (tif_jpeg.c JPEGSetupEncode),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-7595,cve_2017_7595_cwe369_libtiff_jpeg_divzero +CVE-2017-7962,CWE-369,CWE-369,ImageWorsener (imagew-gif.c),PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-7962,cve_2017_7962_cwe369_imageworsener_gif_divzero +CVE-2007-4268,CWE-681,CWE-681,Apple Mac OS X Networking,PREVENTED_COMPILETIME,True,a negative signed length is compared against an unsigned bound,mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2007-4268,compile_fail_cve_2007_4268_cwe681_apple_net_signedness +CVE-2008-1721,CWE-681,CWE-681,CPython zlib extension module,PREVENTED_COMPILETIME,True,a negative signed length is compared against an unsigned bound (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2008-1721,compile_fail_cve_2008_1721_cwe681_python_zlib_signedness +CVE-2008-3282,CWE-681,CWE-681,"OpenOffice.org (rtl_allocateMemory, 64-bit)",PREVENTED_RUNTIME,True,a 64-bit allocation size is truncated when stored into a 32-bit field,mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2008-3282,cve_2008_3282_cwe681_openoffice_alloc_truncation +CVE-2009-0231,CWE-681,CWE-681,Microsoft Windows (T2EMBED.DLL EOT),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2009-0231,compile_fail_cve_2009_0231_cwe681_windows_eot_signedness +CVE-2015-3406,CWE-681,CWE-681,Module::Signature (Perl),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2015-3406,compile_fail_cve_2015_3406_cwe681_module_signature_signedness +CVE-2016-3074,CWE-681,CWE-681,GD Graphics Library (libgd),PREVENTED_COMPILETIME,True,a signed size is added to an unsigned offset (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-3074,compile_fail_cve_2016_3074_cwe681_libgd_signedness +CVE-2017-12140,CWE-681,CWE-681,ImageMagick (coders/dcm.c),PREVENTED_RUNTIME,True,"a 64-bit value stored into a 32-bit field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-12140,cve_2017_12140_cwe681_imagemagick_dcm_truncation +CVE-2017-7308,CWE-681,CWE-681,Linux kernel (packet_set_ring in af_packet.c),PREVENTED_RUNTIME,True,"a 32-bit block size is stored into a 16-bit field, truncating the value",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-7308,cve_2017_7308_cwe681_kernel_afpacket_truncation +CVE-2018-1000224,CWE-681,CWE-681,Godot Engine,PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-1000224,compile_fail_cve_2018_1000224_cwe681_godot_signedness +CVE-2018-11262,CWE-681,CWE-681,Android for MSM (QRD),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-11262,compile_fail_cve_2018_11262_cwe681_android_qrd_signedness +CVE-2018-3999,CWE-681,CWE-681,Atlantis Word Processor (JPEG parser),PREVENTED_RUNTIME,True,"a wider value stored into a narrower field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-3999,cve_2018_3999_cwe681_atlantis_jpeg_truncation +CVE-2018-5251,CWE-681,CWE-681,libming (readSBits),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-5251,compile_fail_cve_2018_5251_cwe681_libming_sbits_signedness +CVE-2018-5711,CWE-681,CWE-681,GD Graphics Library (gd_gif_in.c),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-5711,compile_fail_cve_2018_5711_cwe681_libgd_gif_signedness +CVE-2018-8786,CWE-681,CWE-681,FreeRDP (update_read_bitmap_update),PREVENTED_RUNTIME,True,"a 32-bit rectangle count is stored into a 16-bit field, truncating the value",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-8786,cve_2018_8786_cwe681_freerdp_bitmap_truncation +CVE-2019-1010204,CWE-681,CWE-681,GNU binutils gold,PREVENTED_COMPILETIME,True,a signed size is compared against an unsigned bound (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-1010204,compile_fail_cve_2019_1010204_cwe681_binutils_gold_signedness +CVE-2019-10624,CWE-681,CWE-681,Qualcomm vendor command handler,PREVENTED_RUNTIME,True,"a wide length is stored into an 8-bit field, truncating the value",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-10624,cve_2019_10624_cwe681_libiec_u8_truncation +CVE-2019-14563,CWE-681,CWE-681,EDK II,PREVENTED_RUNTIME,True,"a 64-bit value stored into a 32-bit field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-14563,cve_2019_14563_cwe681_edk2_truncation +CVE-2019-14842,CWE-681,CWE-681,NBD (structured reply),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-14842,compile_fail_cve_2019_14842_cwe681_nbd_signedness +CVE-2019-16778,CWE-681,CWE-681,TensorFlow (UnsortedSegmentSum),PREVENTED_RUNTIME,True,"a 64-bit index is stored into a 32-bit field, truncating the value",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-16778,cve_2019_16778_cwe681_tensorflow_index_truncation +CVE-2019-19945,CWE-681,CWE-681,OpenWrt uhttpd,PREVENTED_COMPILETIME,True,a negative signed length is added to an unsigned offset,mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-19945,compile_fail_cve_2019_19945_cwe681_openwrt_uhttpd_signedness +CVE-2019-19958,CWE-681,CWE-681,libIEC61850 (StringUtils),PREVENTED_RUNTIME,True,"a wider value stored into a narrower field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-19958,cve_2019_19958_cwe681_libiec_str_truncation +CVE-2019-7310,CWE-681,CWE-681,Poppler (XRef::getEntry in XRef.cc),PREVENTED_COMPILETIME,True,a negative signed index is compared against an unsigned table size,mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2019-7310,compile_fail_cve_2019_7310_cwe681_poppler_xref_signedness +CVE-2020-13545,CWE-681,CWE-681,TextMaker (document parsing),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2020-13545,compile_fail_cve_2020_13545_cwe681_textmaker_signedness +CVE-2020-1913,CWE-681,CWE-681,Facebook Hermes (JS interpreter),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2020-1913,compile_fail_cve_2020_1913_cwe681_hermes_signedness +CVE-2020-4032,CWE-681,CWE-681,FreeRDP (update_recv),PREVENTED_RUNTIME,True,"a wider value stored into a narrower field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2020-4032,cve_2020_4032_cwe681_freerdp_updaterecv_truncation +CVE-2021-21860,CWE-681,CWE-681,MPEG-4 decoder,PREVENTED_RUNTIME,True,"a wider value stored into a narrower field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2021-21860,cve_2021_21860_cwe681_mpeg4_21860_truncation +CVE-2021-21861,CWE-681,CWE-681,MPEG-4 decoder,PREVENTED_RUNTIME,True,"a wider value stored into a narrower field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2021-21861,cve_2021_21861_cwe681_mpeg4_21861_truncation +CVE-2021-27219,CWE-681,CWE-681,GNOME GLib (g_byte_array),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2021-27219,compile_fail_cve_2021_27219_cwe681_glib_bytearray_signedness +CVE-2021-36357,CWE-681,CWE-681,OpenPOWER firmware (unpack_timestamp),PREVENTED_RUNTIME,True,"a 64-bit value stored into a 32-bit field, truncating it",mixed,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2021-36357,cve_2021_36357_cwe681_openpower_ts_truncation +CVE-2022-27882,CWE-681,CWE-681,OpenBSD (slaacd),PREVENTED_COMPILETIME,True,a signed value combined with an unsigned value (signed/unsigned confusion),mixed,none,compile-fail,PASS,https://nvd.nist.gov/vuln/detail/CVE-2022-27882,compile_fail_cve_2022_27882_cwe681_openbsd_slaacd_signedness +CVE-2011-1573,CWE-682,CWE-682,Linux kernel SCTP (sm_make_chunk.c),PREVENTED_BOUNDED,True,"a remaining length omits a term, exceeding the known available buffer",u8,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2011-1573,cve_2011_1573_cwe682_kernel_sctp_bounded +CVE-2011-3062,CWE-682,CWE-682,OpenType Sanitizer (as used in Google Chrome),PREVENTED_BOUNDED,True,an index is computed one too large for a buffer of known size,u8,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2011-3062,cve_2011_3062_cwe682_ots_offbyone_bounded +CVE-2016-7433,CWE-682,CWE-682,NTP,NOT_PREVENTED,False,a value is combined with the wrong operand; the arithmetic stays in range,u32,none,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2016-7433,cve_2016_7433_cwe682_ntp_calc_notprevented +CVE-2017-11537,CWE-682,CWE-682,ImageMagick (WritePALMImage),PREVENTED_RUNTIME,True,division (value / depth) with a zero depth from crafted parameters,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-11537,cve_2017_11537_cwe682_imagemagick_palm_divzero +CVE-2017-8326,CWE-682,CWE-682,ImageWorsener,PREVENTED_RUNTIME,True,left shift whose result exceeds the type width,u32,std::overflow_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-8326,cve_2017_8326_cwe682_imageworsener_shl_shl +CVE-2017-8932,CWE-682,CWE-682,Go crypto/elliptic (P-256 ScalarMult),NOT_PREVENTED,False,integer division truncates; the result is in range and well defined,u32,none,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2017-8932,cve_2017_8932_cwe682_go_p256_notprevented +CVE-2018-11790,CWE-682,CWE-682,Apache OpenOffice,PREVENTED_BOUNDED,True,a computed offset exceeds a line buffer of known size,u8,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-11790,cve_2018_11790_cwe682_apache_oo_bounded +CVE-2018-14439,CWE-682,CWE-682,espritblock eos4j (EOS SDK),NOT_PREVENTED,False,integer division truncates; the result is in range and well defined,u32,none,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-14439,cve_2018_14439_cwe682_eos4j_notprevented +CVE-2018-16781,CWE-682,CWE-682,ffjpeg,PREVENTED_RUNTIME,True,division or modulo by an attacker controlled zero,u32,std::domain_error,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-16781,cve_2018_16781_cwe682_ffjpeg_divzero +CVE-2018-20999,CWE-682,CWE-682,orion crate (Rust),NOT_PREVENTED,False,an index computed one too large; the arithmetic stays in range,u32,none,run,PASS,https://nvd.nist.gov/vuln/detail/CVE-2018-20999,cve_2018_20999_cwe682_orion_notprevented +CVE-2016-9377,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2016-9377, +CVE-2017-8905,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-8905, +CVE-2017-0666,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-0666, +CVE-2017-5462,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-5462, +CVE-2017-0342,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-0342, +CVE-2017-0679,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-0679, +CVE-2017-12134,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-12134, +CVE-2017-12135,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-12135, +CVE-2017-13151,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2017-13151, +CVE-2019-17514,CWE-682,,,OUT_OF_SCOPE,False,,,none,excluded,unverified,https://nvd.nist.gov/vuln/detail/CVE-2019-17514, diff --git a/test/cve_corpus/analysis/out_of_scope.csv b/test/cve_corpus/analysis/out_of_scope.csv new file mode 100644 index 0000000..9acb885 --- /dev/null +++ b/test/cve_corpus/analysis/out_of_scope.csv @@ -0,0 +1,11 @@ +cve,category,nvd_url,reason +CVE-2016-9377,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2016-9377,Root cause is x86 software-interrupt emulation on AMD without NRip; not a fixed-width integer arithmetic fault. +CVE-2017-8905,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-8905,Root cause is mishandling of a 64-bit failsafe callback control flow; not a reducible arithmetic operation. +CVE-2017-0666,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-0666,Android media framework advisory gives no disclosed arithmetic expression to reduce. +CVE-2017-5462,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-5462,Root cause is DRBG internal state update in NSS; a cryptographic state defect, not fixed-width integer arithmetic. +CVE-2017-0342,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-0342,NVIDIA kernel-mode driver advisory discloses no arithmetic expression to reduce. +CVE-2017-0679,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-0679,Android media framework RCE with no disclosed arithmetic root cause. +CVE-2017-12134,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-12134,Root cause is Xen block-device page-merge logic (xen_biovec_phys_mergeable); not a fixed-width arithmetic operation. +CVE-2017-12135,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-12135,Xen grant-table handling defect; not a reducible integer arithmetic fault. +CVE-2017-13151,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2017-13151,Android libmpeg2 RCE with no disclosed arithmetic expression to reduce. +CVE-2019-17514,CWE-682,https://nvd.nist.gov/vuln/detail/CVE-2019-17514,Documentation issue in the Python glob module; not a code arithmetic fault at all. diff --git a/test/cve_corpus/analysis/results.adoc b/test/cve_corpus/analysis/results.adoc new file mode 100644 index 0000000..5999de6 --- /dev/null +++ b/test/cve_corpus/analysis/results.adoc @@ -0,0 +1,40 @@ +// Generated by aggregate.py. Do not edit by hand. += CVE corpus results + +This section is generated from the corpus metadata by `test/cve_corpus/analysis/aggregate.py`. + +== Disposition funnel + +[cols="1,1,1,1,1,1",options="header"] +|=== +|Category |Examined |Out of scope |In scope |Prevented |Not prevented +|CWE-190 |30 |0 |30 |30 |0 +|CWE-191 |30 |0 |30 |30 |0 +|CWE-681 |30 |0 |30 |30 |0 +|CWE-369 |30 |0 |30 |30 |0 +|CWE-682 |20 |10 |10 |6 |4 +|All |140 |10 |130 |126 |4 +|=== + +== Prevention rate by category + +The "by default" column counts detection with the default checked types alone; the "incl. bounded" column adds cases prevented once a value's domain is expressed with a bounded type. + +[cols="1,3,1,1,1,1,1",options="header"] +|=== +|CWE |Weakness |In scope |Prevented by default |Prevented incl. bounded |Prevention rate (95% Wilson CI) |McNemar p +|CWE-190 |Integer Overflow or Wraparound |30 |29 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-191 |Integer Underflow |30 |30 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-681 |Incorrect Conversion between Numeric Types |30 |30 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-369 |Divide By Zero |30 |30 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-682 |Incorrect Calculation (negative control) |10 |3 |6 |60.0% (31.3% to 83.2%) |0.0312 +|POOLED |All categories |130 |122 |126 |96.9% (92.4% to 98.8%) |2.35e-38 +|=== + +Category averaged prevention rate (unweighted mean of the per category rates): 92.0%. + +== Reading these numbers + +The native baseline detects zero of these faults by construction, since each CVE shipped in native integer code. Every prevented case is therefore a discordant pair favoring safe_numbers, so the McNemar p value is ceilinged by design: it certifies that the asymmetry is not chance, and it is not an effect size. The prevention rate and its Wilson interval are the primary result, bounded by the genuine failure mode visible in the not prevented cases. + +In the CWE-682 negative control the gap between the two prevented columns is the contribution of bounded types: calculation errors whose wrong result is used as an index, offset, or length into a buffer of known size are caught when that domain is declared with a bounded type, even though the arithmetic itself does not overflow. The cases that remain not prevented are in range value errors (rounding, a wrong cryptographic result, a floating point mishandling) where no bound applies. diff --git a/test/cve_corpus/analysis/results_by_cwe.csv b/test/cve_corpus/analysis/results_by_cwe.csv new file mode 100644 index 0000000..5a25839 --- /dev/null +++ b/test/cve_corpus/analysis/results_by_cwe.csv @@ -0,0 +1,7 @@ +category,title,n_total,n_out_of_scope,n_in_scope,n_prevented,n_prevented_default,n_not_prevented,prevention_rate,wilson_lo,wilson_hi,prevented_default_rate,mcnemar_two_sided_p +CWE-190,Integer Overflow or Wraparound,30,0,30,30,29,0,1.0000,0.8865,1.0000,0.9667,1.86e-09 +CWE-191,Integer Underflow,30,0,30,30,30,0,1.0000,0.8865,1.0000,1.0000,1.86e-09 +CWE-681,Incorrect Conversion between Numeric Types,30,0,30,30,30,0,1.0000,0.8865,1.0000,1.0000,1.86e-09 +CWE-369,Divide By Zero,30,0,30,30,30,0,1.0000,0.8865,1.0000,1.0000,1.86e-09 +CWE-682,Incorrect Calculation (negative control),20,10,10,6,3,4,0.6000,0.3127,0.8318,0.3000,0.0312 +POOLED,All categories,140,10,130,126,,,0.9692,0.9236,0.9880,,2.35e-38 From 1a4b7bd7ed120abd6fd69d80bc028d1b7bbc2fcc Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Aug 2026 14:16:30 -0400 Subject: [PATCH 4/5] Run the CVE corpus as part of the normal test suite --- test/Jamfile | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/test/Jamfile b/test/Jamfile index 43c7929..3529aa4 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -328,3 +328,148 @@ run ../examples/basic_bounded_usage.cpp ; compile-fail ../examples/compile_fail_basic_bounded_usage_constexpr.cpp ; run ../examples/safety_profile.cpp : : : : safety_profile_off ; run ../examples/safety_profile.cpp : : : BOOST_SAFE_NUMBERS_INTEGER_SAFETY_PROFILE : safety_profile_on ; + +# --------------------------------------------------------------------------- +# CVE corpus. One self-contained translation unit per real-world integer-fault +# CVE, grouped into per-CWE subdirectories: each proves the native computation +# silently produces the wrong value and that the identical boost::safe_numbers +# computation detects the fault. Machine-readable metadata lives in a +# BOOST_SAFE_NUMBERS_CVE_BEGIN/END comment block at the top of every file; +# analysis/aggregate.py aggregates it into per-CWE prevention rates. Basenames +# embed the CVE id so they are globally unique. +# --------------------------------------------------------------------------- +# CWE-190 +run cve_corpus/cwe190/cve_2002_0391_cwe190_sunrpc_xdrarray_mul.cpp ; +run cve_corpus/cwe190/cve_2002_0639_cwe190_openssh_challenge_mul.cpp ; +run cve_corpus/cwe190/cve_2004_0657_cwe190_ntpd_offset_add.cpp ; +run cve_corpus/cwe190/cve_2004_0788_cwe190_gdkpixbuf_ico_mul.cpp ; +run cve_corpus/cwe190/cve_2004_2013_cwe190_kernel_sctp_debug_mul.cpp ; +run cve_corpus/cwe190/cve_2005_0102_cwe190_evolution_camel_mul.cpp ; +run cve_corpus/cwe190/cve_2005_1141_cwe190_gocr_pnm_mul.cpp ; +run cve_corpus/cwe190/cve_2005_1513_cwe190_qmail_stralloc_add.cpp ; +run cve_corpus/cwe190/cve_2005_2976_cwe190_gtk_xpm_mul.cpp ; +run cve_corpus/cwe190/cve_2006_3198_cwe190_opera_jpeg_mul.cpp ; +run cve_corpus/cwe190/cve_2006_4519_cwe190_gimp_dicom_mul.cpp ; +run cve_corpus/cwe190/cve_2007_0221_cwe190_exchange_imap_add.cpp ; +run cve_corpus/cwe190/cve_2007_2834_cwe190_ooo_tiff_mul.cpp ; +run cve_corpus/cwe190/cve_2007_2949_cwe190_gimp_psd_mul.cpp ; +run cve_corpus/cwe190/cve_2007_3387_cwe190_xpdf_predictor_mul.cpp ; +run cve_corpus/cwe190/cve_2007_4965_cwe190_python_imageop_mul.cpp ; +run cve_corpus/cwe190/cve_2007_6353_cwe190_exiv2_exif_mul.cpp ; +run cve_corpus/cwe190/cve_2008_1374_cwe190_cups_pdftops_mul.cpp ; +run cve_corpus/cwe190/cve_2008_2663_cwe190_ruby_ary_store_mul.cpp ; +run cve_corpus/cwe190/cve_2008_2826_cwe190_kernel_sctp_addrs_mul.cpp ; +run cve_corpus/cwe190/cve_2008_4019_cwe190_excel_rept_mul.cpp ; +run cve_corpus/cwe190/cve_2009_0723_cwe190_lcms_mul.cpp ; +run cve_corpus/cwe190/cve_2009_0946_cwe190_freetype_smooth_mul.cpp ; +run cve_corpus/cwe190/cve_2010_3442_cwe190_kernel_alsa_mul.cpp ; +run cve_corpus/cwe190/cve_2011_1178_cwe190_gimp_pcx_mul.cpp ; +run cve_corpus/cwe190/cve_2012_1185_cwe190_imagemagick_profile_add.cpp ; +run cve_corpus/cwe190/cve_2013_7437_cwe190_potrace_bmp_mul.cpp ; +run cve_corpus/cwe190/cve_2014_4608_cwe190_kernel_lzo_add.cpp ; +run cve_corpus/cwe190/cve_2015_1283_cwe190_expat_getbuffer_add.cpp ; +run cve_corpus/cwe190/cve_2018_13785_cwe190_libpng_width_bounded.cpp ; +# CWE-191 +run cve_corpus/cwe191/cve_2004_0184_cwe191_tcpdump_isakmp_underflow.cpp ; +run cve_corpus/cwe191/cve_2004_0816_cwe191_iptables_underflow.cpp ; +run cve_corpus/cwe191/cve_2004_1002_cwe191_pppd_cbcp_underflow.cpp ; +run cve_corpus/cwe191/cve_2005_0199_cwe191_ngircd_mask_underflow.cpp ; +run cve_corpus/cwe191/cve_2009_3301_cwe191_ooo_ww8_underflow.cpp ; +run cve_corpus/cwe191/cve_2010_2497_cwe191_freetype_glyph_underflow.cpp ; +run cve_corpus/cwe191/cve_2010_4164_cwe191_kernel_x25_underflow.cpp ; +run cve_corpus/cwe191/cve_2010_4529_cwe191_kernel_irda_underflow.cpp ; +run cve_corpus/cwe191/cve_2011_1770_cwe191_kernel_dccp_underflow.cpp ; +run cve_corpus/cwe191/cve_2011_2497_cwe191_kernel_l2cap_underflow.cpp ; +run cve_corpus/cwe191/cve_2011_4031_cwe191_ffmpeg_asfrtp_underflow.cpp ; +run cve_corpus/cwe191/cve_2013_6424_cwe191_xorg_trapezoid_underflow.cpp ; +run cve_corpus/cwe191/cve_2013_6425_cwe191_pixman_trapezoid_underflow.cpp ; +run cve_corpus/cwe191/cve_2014_0497_cwe191_flash_underflow.cpp ; +run cve_corpus/cwe191/cve_2014_8768_cwe191_tcpdump_geonet_underflow.cpp ; +run cve_corpus/cwe191/cve_2014_9087_cwe191_libksba_oid_underflow.cpp ; +run cve_corpus/cwe191/cve_2015_0537_cwe191_rsa_bsafe_underflow.cpp ; +run cve_corpus/cwe191/cve_2015_1208_cwe191_ffmpeg_mov_underflow.cpp ; +run cve_corpus/cwe191/cve_2015_2311_cwe191_capnproto_underflow.cpp ; +run cve_corpus/cwe191/cve_2015_5212_cwe191_libreoffice_underflow.cpp ; +run cve_corpus/cwe191/cve_2016_10166_cwe191_libgd_interp_underflow.cpp ; +run cve_corpus/cwe191/cve_2016_10268_cwe191_libtiff_tiffcp_underflow.cpp ; +run cve_corpus/cwe191/cve_2016_1925_cwe191_lha_header_underflow.cpp ; +run cve_corpus/cwe191/cve_2016_7800_cwe191_graphicsmagick_meta_underflow.cpp ; +run cve_corpus/cwe191/cve_2017_14496_cwe191_dnsmasq_underflow.cpp ; +run cve_corpus/cwe191/cve_2017_15874_cwe191_busybox_unlzma_underflow.cpp ; +run cve_corpus/cwe191/cve_2017_6313_cwe191_gdkpixbuf_icns_underflow.cpp ; +run cve_corpus/cwe191/cve_2017_8911_cwe191_tnef_underflow.cpp ; +run cve_corpus/cwe191/cve_2017_8924_cwe191_kernel_io_ti_underflow.cpp ; +run cve_corpus/cwe191/cve_2017_9214_cwe191_openvswitch_underflow.cpp ; +# CWE-681 +run cve_corpus/cwe681/cve_2008_3282_cwe681_openoffice_alloc_truncation.cpp ; +run cve_corpus/cwe681/cve_2017_12140_cwe681_imagemagick_dcm_truncation.cpp ; +run cve_corpus/cwe681/cve_2017_7308_cwe681_kernel_afpacket_truncation.cpp ; +run cve_corpus/cwe681/cve_2018_3999_cwe681_atlantis_jpeg_truncation.cpp ; +run cve_corpus/cwe681/cve_2018_8786_cwe681_freerdp_bitmap_truncation.cpp ; +run cve_corpus/cwe681/cve_2019_10624_cwe681_libiec_u8_truncation.cpp ; +run cve_corpus/cwe681/cve_2019_14563_cwe681_edk2_truncation.cpp ; +run cve_corpus/cwe681/cve_2019_16778_cwe681_tensorflow_index_truncation.cpp ; +run cve_corpus/cwe681/cve_2019_19958_cwe681_libiec_str_truncation.cpp ; +run cve_corpus/cwe681/cve_2020_4032_cwe681_freerdp_updaterecv_truncation.cpp ; +run cve_corpus/cwe681/cve_2021_21860_cwe681_mpeg4_21860_truncation.cpp ; +run cve_corpus/cwe681/cve_2021_21861_cwe681_mpeg4_21861_truncation.cpp ; +run cve_corpus/cwe681/cve_2021_36357_cwe681_openpower_ts_truncation.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2007_4268_cwe681_apple_net_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2008_1721_cwe681_python_zlib_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2009_0231_cwe681_windows_eot_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2015_3406_cwe681_module_signature_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2016_3074_cwe681_libgd_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2018_1000224_cwe681_godot_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2018_11262_cwe681_android_qrd_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2018_5251_cwe681_libming_sbits_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2018_5711_cwe681_libgd_gif_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2019_1010204_cwe681_binutils_gold_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2019_14842_cwe681_nbd_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2019_19945_cwe681_openwrt_uhttpd_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2019_7310_cwe681_poppler_xref_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2020_13545_cwe681_textmaker_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2020_1913_cwe681_hermes_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2021_27219_cwe681_glib_bytearray_signedness.cpp ; +compile-fail cve_corpus/cwe681/compile_fail_cve_2022_27882_cwe681_openbsd_slaacd_signedness.cpp ; +# CWE-369 +run cve_corpus/cwe369/cve_2004_0804_cwe369_libtiff_dirread_divzero.cpp ; +run cve_corpus/cwe369/cve_2009_1887_cwe369_netsnmp_divzero.cpp ; +run cve_corpus/cwe369/cve_2011_1012_cwe369_kernel_ldm_modzero.cpp ; +run cve_corpus/cwe369/cve_2012_0207_cwe369_kernel_igmp_modzero.cpp ; +run cve_corpus/cwe369/cve_2014_9756_cwe369_libsndfile_divzero.cpp ; +run cve_corpus/cwe369/cve_2015_3418_cwe369_xorg_putimage_divzero.cpp ; +run cve_corpus/cwe369/cve_2015_6855_cwe369_qemu_ide_divzero.cpp ; +run cve_corpus/cwe369/cve_2015_7513_cwe369_kernel_kvm_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_10053_cwe369_imagemagick_tiff_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_10219_cwe369_ghostscript_intersect_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_10266_cwe369_libtiff_10266_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_10267_cwe369_libtiff_10267_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_3622_cwe369_libtiff_predict_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_3623_cwe369_libtiff_rgb2ycbcr_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_4797_cwe369_openjpeg_tcd_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_5323_cwe369_libtiff_fax3_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_6505_cwe369_wireshark_packetbb_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_7499_cwe369_libav_aacsbr_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_8667_cwe369_qemu_rc4030_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_8669_cwe369_qemu_serial_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_8691_cwe369_jasper_siz_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_8697_cwe369_potrace_bmnew_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_9112_cwe369_openjpeg_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_9265_cwe369_libming_mp3_divzero.cpp ; +run cve_corpus/cwe369/cve_2016_9922_cwe369_qemu_cirrus_divzero.cpp ; +run cve_corpus/cwe369/cve_2017_6833_cwe369_audiofile_runpull_divzero.cpp ; +run cve_corpus/cwe369/cve_2017_6835_cwe369_audiofile_reset1_divzero.cpp ; +run cve_corpus/cwe369/cve_2017_7448_cwe369_lepton_fb_divzero.cpp ; +run cve_corpus/cwe369/cve_2017_7595_cwe369_libtiff_jpeg_divzero.cpp ; +run cve_corpus/cwe369/cve_2017_7962_cwe369_imageworsener_gif_divzero.cpp ; +# CWE-682 +run cve_corpus/cwe682/cve_2011_1573_cwe682_kernel_sctp_bounded.cpp ; +run cve_corpus/cwe682/cve_2011_3062_cwe682_ots_offbyone_bounded.cpp ; +run cve_corpus/cwe682/cve_2016_7433_cwe682_ntp_calc_notprevented.cpp ; +run cve_corpus/cwe682/cve_2017_11537_cwe682_imagemagick_palm_divzero.cpp ; +run cve_corpus/cwe682/cve_2017_8326_cwe682_imageworsener_shl_shl.cpp ; +run cve_corpus/cwe682/cve_2017_8932_cwe682_go_p256_notprevented.cpp ; +run cve_corpus/cwe682/cve_2018_11790_cwe682_apache_oo_bounded.cpp ; +run cve_corpus/cwe682/cve_2018_14439_cwe682_eos4j_notprevented.cpp ; +run cve_corpus/cwe682/cve_2018_16781_cwe682_ffjpeg_divzero.cpp ; +run cve_corpus/cwe682/cve_2018_20999_cwe682_orion_notprevented.cpp ; From 8874534e893a34fe845b46989f81b81bede3db30 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Aug 2026 14:16:48 -0400 Subject: [PATCH 5/5] Add empirical evaluation documentation page --- doc/modules/ROOT/nav.adoc | 1 + .../ROOT/pages/empirical_evaluation.adoc | 177 ++++++++++++++++++ doc/modules/ROOT/partials/cve_results.adoc | 40 ++++ 3 files changed, 218 insertions(+) create mode 100644 doc/modules/ROOT/pages/empirical_evaluation.adoc create mode 100644 doc/modules/ROOT/partials/cve_results.adoc diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index 37a22a7..0c619eb 100644 --- a/doc/modules/ROOT/nav.adoc +++ b/doc/modules/ROOT/nav.adoc @@ -1,6 +1,7 @@ * xref:overview.adoc[] * xref:design.adoc[] * xref:verification.adoc[] +* xref:empirical_evaluation.adoc[] * xref:compile_time_checks.adoc[] * xref:examples.adoc[] ** xref:examples.adoc#examples_basic_usage[Basic Usage] diff --git a/doc/modules/ROOT/pages/empirical_evaluation.adoc b/doc/modules/ROOT/pages/empirical_evaluation.adoc new file mode 100644 index 0000000..7dd314b --- /dev/null +++ b/doc/modules/ROOT/pages/empirical_evaluation.adoc @@ -0,0 +1,177 @@ += Empirical Evaluation Against Real CVEs +:idprefix: empirical_ + +[#empirical_motivation] +== Motivation + +The xref:design.adoc[design rationale] argues that arithmetic safety is a dangerous +and under discussed class of bugs, and the xref:verification.adoc[verification] page +establishes that the fundamental operations are correct for all inputs by transcription +from Why3 proofs. Those two arguments answer "is the mechanism sound." This page answers +a different and complementary question: "how often would the mechanism, if adopted, have +engaged on real historical vulnerabilities." + +To answer it we assembled a corpus of real, publicly disclosed CVEs whose root cause is an +integer arithmetic fault, grouped by CWE, and for each one we reproduced the specific +faulting computation that the disclosure and its patch identify. Each corpus entry is a +self contained test that proves two things under identical inputs: the native fixed width +computation silently produces the same incorrect value the vulnerability is attributed to, +and the identical computation written with `boost::safe_numbers` detects the fault at the +faulting operation, either by throwing at runtime or by failing to compile. + +The corpus, its per file metadata, the analysis script, and the machine generated tables +live in +https://github.com/cppalliance/safe_numbers/tree/develop/test/cve_corpus[test/cve_corpus]. +The full methodology, inclusion and exclusion criteria, and threats to validity are in the +corpus README. + +[#empirical_claim] +== The claim, stated carefully + +We reproduce the arithmetic fault. We do not re run the original programs. The defensible +claim is therefore a counterfactual about the arithmetic mechanism in isolation: + +[quote] +For each in scope CVE the native fixed width computation silently produces the incorrect +value the disclosure attributes the vulnerability to, whereas the identical computation +written with boost::safe_numbers halts at the faulting operation with a typed, catchable +fault. Had that computation been written with the library under its default policy, the +specific silent miscalculation identified as the root cause would have been converted into +a controlled, observable failure rather than propagating as a valid looking value. + +We do not claim that the entire original program, with its full state and control flow, +would have been immune. The library acts at the arithmetic root, upstream of the downstream +memory safety consequence. + +[#empirical_method] +== Method in brief + +CVEs are sourced from the NVD by CWE, so each entry sits in a category the National +Vulnerability Database itself assigned, not one we reassigned. Every examined CVE is placed +in exactly one disposition, and nothing is silently dropped: + +* `PREVENTED_RUNTIME`: the safe computation throws at the faulting operation. +* `PREVENTED_COMPILETIME`: porting to safe types makes the faulting expression ill formed + (for example a mixed signedness comparison or a mixed width operation). +* `PREVENTED_BOUNDED`: the value's legal domain is expressed with a bounded type, which + rejects the out of domain input before any arithmetic runs. +* `NOT_PREVENTED`: a genuine integer arithmetic CVE whose faulting value is representable + and in range, so the library cannot detect it. These count in the denominator. +* `OUT_OF_SCOPE`: on reduction, not a fixed width integer arithmetic fault. Recorded and + reported separately, removed from the denominator. + +To guard against a result that only looks good because the categories were chosen to +flatter the library, the study includes CWE-682 (Incorrect Calculation) as a negative +control, a category where many defects are logic errors the library cannot catch and where +we therefore expect a distinctly lower prevention rate. + +The current corpus is a curated (purposive) sample: from the by-CWE pools we selected CVEs +whose arithmetic root cause is reducible to a self contained snippet. The per category +prevention rate should therefore be read as conditional on that reducibility, and the +credibility of the result rests on the negative control and the honest not prevented cases +rather than on a claim of random sampling. The corpus README documents the sampling +methodology and the threats to validity in full. + +include::partial$cve_results.adoc[leveloffset=+1] + +[#empirical_bounded] +== Bounded types: a precondition layer + +Beyond the default checked types, every primary-category entry in the corpus carries a third +arm that declares the value's legal domain with a bounded type. This models the common case +where a valid range is known independently of the computation: a length that must be at least +a header size, a divisor that must be non zero, an index into a buffer of known size. +Declaring that domain rejects a malicious input at the boundary, before the arithmetic runs +at all, which is a second and earlier line of defense than the operation-level check. + +For example, an index into a 150-element buffer has the domain 0 through 149: + +[source,cpp] +---- +using boost::safe_numbers::bounded_uint; +using boost::safe_numbers::u8; + +using table_index = bounded_uint<0U, 149U>; // valid indices for a 150-element buffer + +const u8 base {100U}; +const u8 length {50U}; +const u8 end_index {base + length}; // 150: correct arithmetic, no overflow + +// The default checked type does not object: 100 + 50 is representable. It is the declared +// index domain that catches the off-by-one when the value is materialized as an index: +(void) table_index{end_index}; // throws std::domain_error +---- + +The addition is correct and does not overflow, so the default check stays silent. The +declared index domain is what catches the off-by-one. + +[NOTE] +==== +One primary-category case is prevented only through a bounded type, which is why the CWE-190 +row reads 29 prevented by default and 30 including bounded. In CVE-2018-13785 (libpng) an +oversized image width flows into a `row_factor` calculation that overflows and then divides +by zero. The oversized width is itself a representable `u32` value, so the default checked +type has no reason to reject it at construction; prevention comes from declaring the width's +documented domain (libpng enforces a user width limit, one million by default) as a +`bounded_uint`, which rejects the value at the boundary before the calculation runs. + +This is a modeling choice that mirrors libpng's own fix. The downstream `row_factor` +overflow and the divide-by-zero would each be caught by the default checked types as well, so +the same CVE could have been reproduced as a runtime-prevented case. It is classified as +bounded on purpose, to show the domain-precondition path on a primary-category CVE rather +than only on the CWE-682 control. +==== + +=== Where bounded types change the outcome: the CWE-682 control + +The negative control makes the effect concrete. Of its ten in-scope cases, three are +prevented by the default checked types (they are divide-by-zero or shift faults that the NVD +happened to tag as calculation errors). Declaring domains with bounded types prevents three +more, raising the control from three prevented to six: + +* an off-by-one index used against a fixed-size table (the example above, CVE-2011-3062), +* a length that omits a padding term and exceeds the real available space (CVE-2011-1573), and +* a file offset that lands past a known line buffer (CVE-2018-11790). + +In each, the wrong result is used as an index, offset, or length into a buffer of +independently known size, so the out-of-domain value is caught when it is formed. The bound +must come from an independent quantity, the real buffer size, never from the correct answer. + +The remaining four control cases stay unprevented because their wrong result is a valid +in-domain value: a rounded time value (CVE-2016-7433), a wrong elliptic-curve point +(CVE-2017-8932), a mishandled floating point number (CVE-2018-14439), and a wrong +cipher-reset output (CVE-2018-20999). No bound applies to these, which is exactly why the +negative control still marks the library's limit. The "by default" and "incl. bounded" +columns in the table above quantify this split: three by default, six once domains are +declared, four beyond reach of either. + +[#empirical_reproduce] +== Reproducing these numbers + +The corpus is built and run like any other test in the suite, and the statistics are +regenerated from the metadata by a dependency free Python script: + +[source,bash] +---- +# build and run the corpus (and confirm the compile-fail entries fail to compile) +b2 libs/safe_numbers/test + +# regenerate corpus.csv, results_by_cwe.csv, results.adoc, and the doc partial +python3 libs/safe_numbers/test/cve_corpus/analysis/aggregate.py +---- + +The script validates every metadata block, cross checks the recorded classification against +the test outcome when a results file is supplied, and exits nonzero on any inconsistency, so +the corpus can be gated in continuous integration. + +[#empirical_validity] +== How to read the significance + +The native baseline detects zero of these faults by construction, since every CVE shipped +in native integer code. Every prevented case is therefore a discordant pair favoring +safe_numbers, so the paired McNemar test is ceilinged by design: it certifies that the +asymmetry is not chance, and it is not an effect size. The scientifically meaningful +quantity is the prevention rate and its Wilson confidence interval, which is bounded by the +genuine failure mode visible in the not prevented cases and in the negative control. This +empirical coverage result complements, and does not replace, the soundness result on the +xref:verification.adoc[verification] page. diff --git a/doc/modules/ROOT/partials/cve_results.adoc b/doc/modules/ROOT/partials/cve_results.adoc new file mode 100644 index 0000000..5999de6 --- /dev/null +++ b/doc/modules/ROOT/partials/cve_results.adoc @@ -0,0 +1,40 @@ +// Generated by aggregate.py. Do not edit by hand. += CVE corpus results + +This section is generated from the corpus metadata by `test/cve_corpus/analysis/aggregate.py`. + +== Disposition funnel + +[cols="1,1,1,1,1,1",options="header"] +|=== +|Category |Examined |Out of scope |In scope |Prevented |Not prevented +|CWE-190 |30 |0 |30 |30 |0 +|CWE-191 |30 |0 |30 |30 |0 +|CWE-681 |30 |0 |30 |30 |0 +|CWE-369 |30 |0 |30 |30 |0 +|CWE-682 |20 |10 |10 |6 |4 +|All |140 |10 |130 |126 |4 +|=== + +== Prevention rate by category + +The "by default" column counts detection with the default checked types alone; the "incl. bounded" column adds cases prevented once a value's domain is expressed with a bounded type. + +[cols="1,3,1,1,1,1,1",options="header"] +|=== +|CWE |Weakness |In scope |Prevented by default |Prevented incl. bounded |Prevention rate (95% Wilson CI) |McNemar p +|CWE-190 |Integer Overflow or Wraparound |30 |29 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-191 |Integer Underflow |30 |30 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-681 |Incorrect Conversion between Numeric Types |30 |30 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-369 |Divide By Zero |30 |30 |30 |100.0% (88.6% to 100.0%) |1.86e-09 +|CWE-682 |Incorrect Calculation (negative control) |10 |3 |6 |60.0% (31.3% to 83.2%) |0.0312 +|POOLED |All categories |130 |122 |126 |96.9% (92.4% to 98.8%) |2.35e-38 +|=== + +Category averaged prevention rate (unweighted mean of the per category rates): 92.0%. + +== Reading these numbers + +The native baseline detects zero of these faults by construction, since each CVE shipped in native integer code. Every prevented case is therefore a discordant pair favoring safe_numbers, so the McNemar p value is ceilinged by design: it certifies that the asymmetry is not chance, and it is not an effect size. The prevention rate and its Wilson interval are the primary result, bounded by the genuine failure mode visible in the not prevented cases. + +In the CWE-682 negative control the gap between the two prevented columns is the contribution of bounded types: calculation errors whose wrong result is used as an index, offset, or length into a buffer of known size are caught when that domain is declared with a bounded type, even though the arithmetic itself does not overflow. The cases that remain not prevented are in range value errors (rounding, a wrong cryptographic result, a floating point mishandling) where no bound applies.