Hi, This patches fixes * the stack overflow reported in PR68159 in cplus_demangle_print_callback, * a potential stack overflow in d_demangle_callback * a potential stack overflow in is_ctor_or_dtor, and * six potential buffer overflows (initialise less memory than needed due to integer overflow).
The stack overflow reported in PR68159 occurs due to assigning an array too much memory from the stack (447kb). Similar stack overflows might occur in the remaining five dynamically allocated arrays in this and the other two functions. Since the array size is controlled from the mangled string, we better safeguard from integer overflows and thus buffer overflows for these six arrays. The patch allocates memory from the heap (xmalloc) instead of from the stack (dynamic arrays, alloca), checks for integer overflows, and frees the allocated memory before function return / abort. Best regards, - Marcel Index: ChangeLog =================================================================== --- ChangeLog (revision 235941) +++ ChangeLog (working copy) @@ -1,3 +1,14 @@ +2016-05-06 Marcel Böhme <boehme.mar...@gmail.com> + + PR c++/68159 + * cp-demangle.c: Check for overflow and allocate arrays of user-defined + size on the heap, not on the stack. + (CP_DYNAMIC_ARRAYS): Remove redundant definition. + (cplus_demangle_print_callback): Check for overflow. Allocate memory + for two arrays on the heap. Free memory before return / exit. + (d_demangle_callback): Likewise. + (is_ctor_or_dtor): Likewise. + 2016-05-02 Marcel Böhme <boehme.mar...@gmail.com> PR c++/70498 Index: cp-demangle.c =================================================================== --- cp-demangle.c (revision 235941) +++ cp-demangle.c (working copy) @@ -186,20 +186,6 @@ static void d_init_info (const char *, int, size_t #define CP_STATIC_IF_GLIBCPP_V3 #endif /* ! defined(IN_GLIBCPP_V3) */ -/* See if the compiler supports dynamic arrays. */ - -#ifdef __GNUC__ -#define CP_DYNAMIC_ARRAYS -#else -#ifdef __STDC__ -#ifdef __STDC_VERSION__ -#if __STDC_VERSION__ >= 199901L -#define CP_DYNAMIC_ARRAYS -#endif /* __STDC__VERSION >= 199901L */ -#endif /* defined (__STDC_VERSION__) */ -#endif /* defined (__STDC__) */ -#endif /* ! defined (__GNUC__) */ - /* We avoid pulling in the ctype tables, to prevent pulling in additional unresolved symbols when this code is used in a library. FIXME: Is this really a valid reason? This comes from the original @@ -4125,26 +4111,26 @@ cplus_demangle_print_callback (int options, struct d_print_info dpi; d_print_init (&dpi, callback, opaque, dc); + + if (dpi.num_copy_templates > INT_MAX / (int) sizeof (*dpi.copy_templates)) + xmalloc_failed(INT_MAX); + dpi.copy_templates = + (struct d_print_template *) xmalloc (dpi.num_copy_templates + * sizeof (*dpi.copy_templates)); - { -#ifdef CP_DYNAMIC_ARRAYS - __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes]; - __extension__ struct d_print_template temps[dpi.num_copy_templates]; + if (dpi.num_saved_scopes > INT_MAX / (int) sizeof (*dpi.saved_scopes)) + xmalloc_failed(INT_MAX); + dpi.saved_scopes = + (struct d_saved_scope *) xmalloc (dpi.num_saved_scopes + * sizeof (*dpi.saved_scopes)); - dpi.saved_scopes = scopes; - dpi.copy_templates = temps; -#else - dpi.saved_scopes = alloca (dpi.num_saved_scopes - * sizeof (*dpi.saved_scopes)); - dpi.copy_templates = alloca (dpi.num_copy_templates - * sizeof (*dpi.copy_templates)); -#endif + d_print_comp (&dpi, options, dc); - d_print_comp (&dpi, options, dc); - } - d_print_flush (&dpi); + free(dpi.copy_templates); + free(dpi.saved_scopes); + return ! d_print_saw_error (&dpi); } @@ -5945,18 +5931,17 @@ d_demangle_callback (const char *mangled, int opti cplus_demangle_init_info (mangled, options, strlen (mangled), &di); - { -#ifdef CP_DYNAMIC_ARRAYS - __extension__ struct demangle_component comps[di.num_comps]; - __extension__ struct demangle_component *subs[di.num_subs]; + if (di.num_comps > INT_MAX / (int) sizeof (*di.comps)) + xmalloc_failed(INT_MAX); + di.comps = (struct demangle_component *) xmalloc (di.num_comps + * sizeof (*di.comps)); - di.comps = comps; - di.subs = subs; -#else - di.comps = alloca (di.num_comps * sizeof (*di.comps)); - di.subs = alloca (di.num_subs * sizeof (*di.subs)); -#endif + if (di.num_subs > INT_MAX / (int) sizeof (*di.subs)) + xmalloc_failed(INT_MAX); + di.subs = (struct demangle_component **) xmalloc (di.num_subs + * sizeof (*di.subs)); + { switch (type) { case DCT_TYPE: @@ -5977,6 +5962,8 @@ d_demangle_callback (const char *mangled, int opti d_advance (&di, strlen (d_str (&di))); break; default: + free (di.comps); + free (di.subs); abort (); /* We have listed all the cases. */ } @@ -5995,7 +5982,8 @@ d_demangle_callback (const char *mangled, int opti ? cplus_demangle_print_callback (options, dc, callback, opaque) : 0; } - + free (di.comps); + free (di.subs); return status; } @@ -6226,18 +6214,17 @@ is_ctor_or_dtor (const char *mangled, cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di); + if (di.num_comps > INT_MAX / (int) sizeof (*di.comps)) + xmalloc_failed(INT_MAX); + di.comps = (struct demangle_component *) xmalloc (di.num_comps + * sizeof (*di.comps)); + + if (di.num_subs > INT_MAX / (int) sizeof (*di.subs)) + xmalloc_failed(INT_MAX); + di.subs = (struct demangle_component **) xmalloc (di.num_subs + * sizeof (*di.subs)); { -#ifdef CP_DYNAMIC_ARRAYS - __extension__ struct demangle_component comps[di.num_comps]; - __extension__ struct demangle_component *subs[di.num_subs]; - di.comps = comps; - di.subs = subs; -#else - di.comps = alloca (di.num_comps * sizeof (*di.comps)); - di.subs = alloca (di.num_subs * sizeof (*di.subs)); -#endif - dc = cplus_demangle_mangled_name (&di, 1); /* Note that because we did not pass DMGL_PARAMS, we don't expect @@ -6279,7 +6266,8 @@ is_ctor_or_dtor (const char *mangled, } } } - + free (di.comps); + free (di.subs); return ret; } Index: testsuite/demangle-expected =================================================================== --- testsuite/demangle-expected (revision 235941) +++ testsuite/demangle-expected (working copy) @@ -4441,3 +4441,8 @@ __vt_90000000000cafebabe _Z80800000000000000000000 _Z80800000000000000000000 +# +# Tests stack overflow + +_ZZN5Eigen9DenseBaseINS_5BlockINS_6MatrixIdLin1ELin1ELi0ELin1ELin1EEELin1ELin1ELb1EEEE10lazyAssignINS_12CwiseUnaryOpIZZN6netops4expr6sampleINS9_12nn6_combinerIN5boost3mpl9vector2_cIiLi0ELi2EEENS9_11rowwise_addINS9_6matmulINS9_12input_matrixINSE_IiLi0ELi0EEENSC_6fusion7vector3INSK_7vector4IN4nnet8mat_sizeIdLi1EEESP_NSO_IiLi0EEENSO_IdLi0EEEEENSK_7vector7ISP_SP_SP_SP_SP_SP_SP_EENSN_11config_dataIN3nn66detail8nn6_modeILb1EEEEEEEEENS9_13weight_matrixINSD_6v_itemIN4mpl_4int_ILi0EEENSD_9vector1_cIiLi2EEELi0EEENSK_7vector6INSK_7vector2ISP_NSN_8vec_sizeIdLi1EEEEES1F_S1F_S1F_S1F_S1F_EEEEEENS13_INS14_INS16_ILi1EEES19_Li0EEES1G_EEEENS9_16logistic_sigmoidINSG_INSH_INS1N_INSG_INSH_INSI_INSE_IiLi0ELi1EEES11_EENS13_INS14_IS17_NS18_IiLi0EEELi0EEES1G_EEEENS13_INS14_IS1J_S1Q_Li0EEES1G_EEEEEENS13_INS14_IS17_NS18_IiLi1EEELi0EEES1G_EEEENS13_INS14_IS1J_S1Y_Li0EEES1G_EEEEEEEEEclINSL_INSM_INS_12SparseMatrixIdLi1EiEENS2_IdLin1ELin1ELi1ELin1ELin1EEENS2_IiLin1ELi1ELi0ELin1ELi1EEENS2_IdLin1ELi1ELi0ELin1ELi1EEEEENST_IS2A_S2A_S2A_S2A_S2A_S2A_S2A_EESZ_EENS1B_INS1C_INS_3MapIS2B_Li1ENS_6StrideILi0ELi0EEEEENS2H_INS2_IdLi1ELin1ELi1ELi1ELin1EEELi1ES2J_EEEES2N_S2N_S2N_S2N_S2N_EEZZNS9_6concatIJNSI_INSE_IiLi0ELi3EEES11_EENS9_7dropoutILb0ES19_NS1N_INS2P_IJNSG_INSH_INSI_INSE_IiLi1ELi0EEES11_EENS13_INS14_IS17_NS18_IiLi3EEELi0EEES1G_EEEENS13_INS14_IS1J_S2V_Li0EEES1G_EEEENSG_INSH_INSI_INSE_IiLi1ELi1EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi2EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi3EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi4EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi5EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi6EEES11_EES2X_EES30_EEEEEEEEES27_EEclIS2G_S2O_ZNS9_6detail11binary_contIS2G_S2O_S3T_NS13_INS14_IS17_NS18_IiLi4EEELi0EEES1G_EEZNSH_IS3T_S3Z_EclIS2G_S2O_ZNS3W_IS2G_S2O_S40_NS13_INS14_IS1J_S3X_Li0EEES1G_EEZNSG_IS40_S43_EclIS2G_S2O_ZNS1N_IS44_EclIS2G_S2O_ZNS9_7concat2IS2R_S46_EclIS2G_S2O_ZNS3W_IS2G_S2O_S49_NS13_INS14_IS17_NS18_IiLi5EEELi0EEES1G_EEZNSH_IS49_S4D_EclIS2G_S2O_ZNS3W_IS2G_S2O_S4E_NS13_INS14_IS1J_S4B_Li0EEES1G_EEZNSG_IS4E_S4H_EclIS2G_S2O_ZNS9_11concat_zeroIS4I_EclIS2G_S2O_ZNS9_20softmax_crossentropyIS4L_EclIS2G_S2O_ZNKS8_11derived_ptrIS4O_E5fpropIS2G_S2O_EEDaRKT_RKT0_EUlOS4T_OS4W_OT1_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_OT2_E_EEDaRKNS4Q_IS51_EERKNS4Q_IS56_EES4V_S4Y_OKT3_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_S57_E_EEDaS5B_S5E_S4V_S4Y_S5H_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E0_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_S57_E_EEDaS5B_S5E_S4V_S4Y_S5H_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_S57_E_EEDaS5B_S5E_S4V_S4Y_S5H_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_ENKUlmRS4T_E0_clINS4Q_IS27_EEEEDamS5R_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_ENKUlS4Z_S50_S52_E_clIRKS2G_RKS2O_KNS_22SparseTimeDenseProductIS2A_S2B_EEEEDaS4Z_S50_S52_EUldE_S64_EEEERS4_RKNS0_IS4T_EEE19__PRETTY_FUNCTION__ +_ZZN5Eigen9DenseBaseINS_5BlockINS_6MatrixIdLin1ELin1ELi0ELin1ELin1EEELin1ELin1ELb1EEEE10lazyAssignINS_12CwiseUnaryOpIZZN6netops4expr6sampleINS9_12nn6_combinerIN5boost3mpl9vector2_cIiLi0ELi2EEENS9_11rowwise_addINS9_6matmulINS9_12input_matrixINSE_IiLi0ELi0EEENSC_6fusion7vector3INSK_7vector4IN4nnet8mat_sizeIdLi1EEESP_NSO_IiLi0EEENSO_IdLi0EEEEENSK_7vector7ISP_SP_SP_SP_SP_SP_SP_EENSN_11config_dataIN3nn66detail8nn6_modeILb1EEEEEEEEENS9_13weight_matrixINSD_6v_itemIN4mpl_4int_ILi0EEENSD_9vector1_cIiLi2EEELi0EEENSK_7vector6INSK_7vector2ISP_NSN_8vec_sizeIdLi1EEEEES1F_S1F_S1F_S1F_S1F_EEEEEENS13_INS14_INS16_ILi1EEES19_Li0EEES1G_EEEENS9_16logistic_sigmoidINSG_INSH_INS1N_INSG_INSH_INSI_INSE_IiLi0ELi1EEES11_EENS13_INS14_IS17_NS18_IiLi0EEELi0EEES1G_EEEENS13_INS14_IS1J_S1Q_Li0EEES1G_EEEEEENS13_INS14_IS17_NS18_IiLi1EEELi0EEES1G_EEEENS13_INS14_IS1J_S1Y_Li0EEES1G_EEEEEEEEEclINSL_INSM_INS_12SparseMatrixIdLi1EiEENS2_IdLin1ELin1ELi1ELin1ELin1EEENS2_IiLin1ELi1ELi0ELin1ELi1EEENS2_IdLin1ELi1ELi0ELin1ELi1EEEEENST_IS2A_S2A_S2A_S2A_S2A_S2A_S2A_EESZ_EENS1B_INS1C_INS_3MapIS2B_Li1ENS_6StrideILi0ELi0EEEEENS2H_INS2_IdLi1ELin1ELi1ELi1ELin1EEELi1ES2J_EEEES2N_S2N_S2N_S2N_S2N_EEZZNS9_6concatIJNSI_INSE_IiLi0ELi3EEES11_EENS9_7dropoutILb0ES19_NS1N_INS2P_IJNSG_INSH_INSI_INSE_IiLi1ELi0EEES11_EENS13_INS14_IS17_NS18_IiLi3EEELi0EEES1G_EEEENS13_INS14_IS1J_S2V_Li0EEES1G_EEEENSG_INSH_INSI_INSE_IiLi1ELi1EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi2EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi3EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi4EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi5EEES11_EES2X_EES30_EENSG_INSH_INSI_INSE_IiLi1ELi6EEES11_EES2X_EES30_EEEEEEEEES27_EEclIS2G_S2O_ZNS9_6detail11binary_contIS2G_S2O_S3T_NS13_INS14_IS17_NS18_IiLi4EEELi0EEES1G_EEZNSH_IS3T_S3Z_EclIS2G_S2O_ZNS3W_IS2G_S2O_S40_NS13_INS14_IS1J_S3X_Li0EEES1G_EEZNSG_IS40_S43_EclIS2G_S2O_ZNS1N_IS44_EclIS2G_S2O_ZNS9_7concat2IS2R_S46_EclIS2G_S2O_ZNS3W_IS2G_S2O_S49_NS13_INS14_IS17_NS18_IiLi5EEELi0EEES1G_EEZNSH_IS49_S4D_EclIS2G_S2O_ZNS3W_IS2G_S2O_S4E_NS13_INS14_IS1J_S4B_Li0EEES1G_EEZNSG_IS4E_S4H_EclIS2G_S2O_ZNS9_11concat_zeroIS4I_EclIS2G_S2O_ZNS9_20softmax_crossentropyIS4L_EclIS2G_S2O_ZNKS8_11derived_ptrIS4O_E5fpropIS2G_S2O_EEDaRKT_RKT0_EUlOS4T_OS4W_OT1_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_OT2_E_EEDaRKNS4Q_IS51_EERKNS4Q_IS56_EES4V_S4Y_OKT3_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_S57_E_EEDaS5B_S5E_S4V_S4Y_S5H_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E0_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_S57_E_EEDaS5B_S5E_S4V_S4Y_S5H_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_EUlS4Z_S50_S52_S57_E_EEDaS5B_S5E_S4V_S4Y_S5H_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_ENKUlmRS4T_E0_clINS4Q_IS27_EEEEDamS5R_EUlS4Z_S50_S52_E_EEDaS4V_S4Y_S52_ENKUlS4Z_S50_S52_E_clIRKS2G_RKS2O_KNS_22SparseTimeDenseProductIS2A_S2B_EEEEDaS4Z_S50_S52_EUldE_S64_EEEERS4_RKNS0_IS4T_EEE19__PRETTY_FUNCTION__