diff options
| -rw-r--r-- | safercpp/safercpp-arr.cpp | 379 | 
1 files changed, 269 insertions, 110 deletions
| diff --git a/safercpp/safercpp-arr.cpp b/safercpp/safercpp-arr.cpp index f7644a1..e0f51db 100644 --- a/safercpp/safercpp-arr.cpp +++ b/safercpp/safercpp-arr.cpp @@ -1386,6 +1386,7 @@ class CTypeIndirectionPrefixAndSuffixItem {  public:  	std::string m_prefix_str;  	std::string m_suffix_str; +	std::string m_post_name_suffix_str;  	std::string m_action_species;  	bool m_direct_type_must_be_non_const = false;  }; @@ -1398,6 +1399,7 @@ static CTypeIndirectionPrefixAndSuffixItem generate_type_indirection_prefix_and_  	std::string replacement_code;  	std::string prefix_str;  	std::string suffix_str; +	std::string post_name_suffix_str;  	if (true) {  		for (size_t i = 0; i < indirection_state_stack.size(); i += 1) { @@ -1458,7 +1460,11 @@ static CTypeIndirectionPrefixAndSuffixItem generate_type_indirection_prefix_and_  					/* We're assuming this is a null terminated string. We'll just leave it as a  					 * char[] for now. At some point we'll replace it with an mse::string or whatever. */  					//prefix_str = prefix_str + ""; -					suffix_str = "[" + size_text + "]" + suffix_str; +					if (1 == indirection_state_stack.size()) { +						post_name_suffix_str = post_name_suffix_str + "[" + size_text + "]"; +					} else { +						suffix_str = "[" + size_text + "]" + suffix_str; +					}  				} else {  					if (is_a_function_parameter) {  						prefix_str = prefix_str + "mse::TNullableAnyRandomAccessIterator<"; @@ -1700,6 +1706,7 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con  	std::string replacement_code;  	std::string prefix_str;  	std::string suffix_str; +	std::string post_name_suffix_str;  	auto res4 = generate_type_indirection_prefix_and_suffix(ddcs_ref.m_indirection_state_stack,  			direct_type_is_char_type, direct_type_is_function_type, is_a_function_parameter); @@ -1710,6 +1717,7 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con  	}  	prefix_str = res4.m_prefix_str;  	suffix_str = res4.m_suffix_str; +	post_name_suffix_str = res4.m_post_name_suffix_str;  	bool discard_initializer_option_flag = (std::string::npos != options_str.find("[discard-initializer]"));  	std::string initializer_append_str; @@ -1720,7 +1728,7 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con  		}  	} -	if (("" != prefix_str) || ("" != suffix_str)) { +	if (("" != prefix_str) || ("" != suffix_str)/* || ("" != post_name_suffix_str)*/) {  		changed_from_original = true;  	} else if (("" != ddcs_ref.m_initializer_info_str) ||  			(discard_initializer_option_flag)) { @@ -1751,6 +1759,7 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con  			replacement_code += prefix_str + direct_qtype_str + suffix_str;  			replacement_code += " ";  			replacement_code += variable_name; +			replacement_code += post_name_suffix_str;  			replacement_code += initializer_append_str;  		} else { @@ -2954,6 +2963,102 @@ private:  /**********************************************************************************************************************/ +struct CAllocFunctionInfo { +	bool m_seems_to_be_some_kind_of_malloc_or_realloc = false; +	bool m_seems_to_be_some_kind_of_realloc = false; +	clang::CallExpr::const_arg_iterator m_num_bytes_arg_iter; +	std::string m_num_bytes_arg_source_text; +}; +CAllocFunctionInfo analyze_malloc_resemblance(const clang::CallExpr& call_expr, Rewriter &Rewrite) { +	CAllocFunctionInfo retval; + +	auto CE = &call_expr; +	auto function_decl = CE->getDirectCallee(); +	auto num_args = CE->getNumArgs(); +	if (function_decl && ((1 == num_args) || (2 == num_args))) { +		std::string function_name = function_decl->getNameAsString(); +		static const std::string alloc_str = "alloc"; +		static const std::string realloc_str = "realloc"; +		auto lc_function_name = tolowerstr(function_name); +		bool ends_with_alloc = ((lc_function_name.size() >= alloc_str.size()) +				&& (0 == lc_function_name.compare(lc_function_name.size() - alloc_str.size(), alloc_str.size(), alloc_str))); +		bool ends_with_realloc = (ends_with_alloc && (lc_function_name.size() >= realloc_str.size()) +				&& (0 == lc_function_name.compare(lc_function_name.size() - realloc_str.size(), realloc_str.size(), realloc_str))); +		bool still_potentially_valid1 = (ends_with_alloc && (1 == num_args)) || (ends_with_realloc && (2 == num_args)); +		if (still_potentially_valid1) { +			auto arg_iter = CE->arg_begin(); +			if (ends_with_realloc) { +				arg_iter++; +			} +			bool argIsIntegerType = false; +			if (*arg_iter) { +				argIsIntegerType = (*arg_iter)->getType().split().asPair().first->isIntegerType(); +			} +			if (argIsIntegerType) { +				auto arg_source_range = nice_source_range((*arg_iter)->getSourceRange(), Rewrite); +				std::string arg_source_text; +				if (arg_source_range.isValid()) { +					arg_source_text = Rewrite.getRewrittenText(arg_source_range); +					//auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); + +					bool asterisk_found = false; +					auto sizeof_start_index = arg_source_text.find("sizeof("); +					if (std::string::npos != sizeof_start_index) { +						auto sizeof_end_index = arg_source_text.find(")", sizeof_start_index); +						if (std::string::npos != sizeof_end_index) { +							assert(sizeof_end_index > sizeof_start_index); +							std::string before_str = arg_source_text.substr(0, sizeof_start_index); +							std::string after_str; +							if (sizeof_end_index + 1 < arg_source_text.size()) { +								after_str = arg_source_text.substr(sizeof_end_index + 1); +							} + +							auto index = before_str.size() - 1; +							while (0 <= index) { +								if ('*' == before_str[index]) { +									asterisk_found = true; +								} +								if (!std::isspace(before_str[index])) { +									break; +								} + +								index -= 1; +							} +							if (asterisk_found) { +								before_str = before_str.substr(0, index); +							} else { +								size_t index2 = 0; +								while (after_str.size() > index2) { +									if ('*' == after_str[index2]) { +										asterisk_found = true; +									} +									if (!std::isspace(after_str[index2])) { +										break; +									} + +									index2 += 1; +								} +								if (asterisk_found) { +									after_str = after_str.substr(index2 + 1); +								} +							} +						} +					} +					if (true || asterisk_found) { +						retval.m_num_bytes_arg_iter = arg_iter; +						retval.m_seems_to_be_some_kind_of_malloc_or_realloc = true; +						retval.m_num_bytes_arg_source_text = arg_source_text; +						if (ends_with_realloc) { +							retval.m_seems_to_be_some_kind_of_realloc = true; +						} +					} +				} +			} +		} +	} +	return retval; +} +  class MCSSSVarDecl2 : public MatchFinder::MatchCallback  {  public: @@ -2963,6 +3068,10 @@ public:  	virtual void run(const MatchFinder::MatchResult &MR)  	{  		const DeclaratorDecl* DD = MR.Nodes.getNodeAs<clang::DeclaratorDecl>("mcsssvardecl"); +		const Expr* RHS = MR.Nodes.getNodeAs<clang::Expr>("mcsssvardecl2"); +		const clang::CStyleCastExpr* CCE = MR.Nodes.getNodeAs<clang::CStyleCastExpr>("mcsssvardecl3"); +		//const DeclStmt* DS = MR.Nodes.getNodeAs<clang::DeclStmt>("mcsssvardecl4"); +  		if ((DD != nullptr))  		{  			auto SR = nice_source_range(DD->getSourceRange(), Rewrite); @@ -3014,6 +3123,140 @@ public:  			}  			update_declaration(*DD, Rewrite, m_state1); + +			if (nullptr != RHS) { +				auto rhs_res2 = infer_array_type_info_from_stmt(*RHS, "", (*this).m_state1); +				bool lhs_is_an_indirect_type = is_an_indirect_type(DD->getType()); +				bool rhs_is_an_indirect_type = is_an_indirect_type(RHS->getType()); +				assert(lhs_is_an_indirect_type == rhs_is_an_indirect_type); + +				if (rhs_res2.ddecl_cptr && rhs_res2.update_declaration_flag) { +					update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); +				} + +				if ((nullptr != CCE) && (rhs_res2.ddecl_conversion_state_ptr)) { +					auto cce_QT = CCE->getType(); +					auto rhs_QT = RHS->getType(); +					if (cce_QT == rhs_QT) { +						CIndirectionStateStack rhs_qtype_indirection_state_stack; +						auto direct_rhs_qtype = populateQTypeIndirectionStack(rhs_qtype_indirection_state_stack, rhs_QT); +						auto direct_rhs_qtype_str = direct_rhs_qtype.getAsString(); +						auto casted_expr_ptr = CCE->IgnoreCasts(); +						if (llvm::isa<const clang::CallExpr>(casted_expr_ptr->IgnoreParenCasts())) { +							auto CE = llvm::cast<const clang::CallExpr>(casted_expr_ptr->IgnoreParenCasts()); +							auto alloc_function_info1 = analyze_malloc_resemblance(*CE, Rewrite); +							if (alloc_function_info1.m_seems_to_be_some_kind_of_malloc_or_realloc) { +								/* This seems to be some kind of malloc/realloc function. These case should not be +								 * handled here. They are handled elsewhere. */ +								return; +							} +						} + +						if ((rhs_qtype_indirection_state_stack.size() + rhs_res2.indirection_level +								== (*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()) +								&& (1 <= (*rhs_res2.ddecl_conversion_state_ptr).m_indirection_state_stack.size()) +								&& (nullptr != casted_expr_ptr)) { + +							std::string rhs_ddecl_current_direct_qtype_str = (*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype_str; +							auto casted_expr_SR = nice_source_range(casted_expr_ptr->getSourceRange(), Rewrite); +							auto CCESR = nice_source_range(CCE->getSourceRange(), Rewrite); +							auto cast_operation_SR = clang::SourceRange(CCE->getLParenLoc(), CCE->getRParenLoc()); + +							if (cast_operation_SR.isValid() +									&& (("void" == rhs_ddecl_current_direct_qtype_str) || ("const void" == rhs_ddecl_current_direct_qtype_str))) { +								if (ConvertToSCPP) { +									(*rhs_res2.ddecl_conversion_state_ptr).set_current_direct_qtype(direct_rhs_qtype); + +									auto cast_operation_text = Rewrite.getRewrittenText(cast_operation_SR); +									/* This is not the proper way to modify an expression. See the function +									 * CConditionalOperatorReconciliation2ReplacementAction::do_replacement() for an example of +									 * the proper way to do it. But for now this is good enough. */ +									auto res2 = Rewrite.ReplaceText(cast_operation_SR, ""); + +									static const std::string void_str = "void"; +									auto void_pos = (*rhs_res2.ddecl_conversion_state_ptr).m_initializer_info_str.find(void_str); +									if (std::string::npos != void_pos) { +										(*rhs_res2.ddecl_conversion_state_ptr).m_initializer_info_str.replace(void_pos, void_str.length(), direct_rhs_qtype_str); +									} + +									update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); +								} +							} else { +								if (ConvertToSCPP) { +									if (false) { +										(*rhs_res2.ddecl_conversion_state_ptr).set_current_direct_qtype(direct_rhs_qtype); +									} +								} +							} +						} else { +							int q = 7; +						} +					} else { +						int q = 7; +					} +				} + +				int lhs_indirection_level_adjustment = 0; +				auto rhs_res3 = leading_addressof_operator_info_from_stmt(*RHS); +				if (rhs_res3.without_leading_addressof_operator_expr_cptr) { +					assert(rhs_res3.leading_addressof_operator_detected && rhs_res3.addressof_unary_operator_cptr); + +					RHS = rhs_res3.without_leading_addressof_operator_expr_cptr; +					rhs_res2 = infer_array_type_info_from_stmt(*RHS, "", (*this).m_state1); +					lhs_indirection_level_adjustment += 1; + +					const clang::ArraySubscriptExpr* array_subscript_expr_cptr = nullptr; +					if (clang::Stmt::StmtClass::ArraySubscriptExprClass == (*(rhs_res3.without_leading_addressof_operator_expr_cptr)).getStmtClass()) { +						assert(llvm::isa<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr)); +						array_subscript_expr_cptr = llvm::cast<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr); +					} +					if (ConvertToSCPP && array_subscript_expr_cptr) { +						std::shared_ptr<CArray2ReplacementAction> cr_shptr = std::make_shared<CAssignmentTargetConstrainsAddressofArraySubscriptExprArray2ReplacementAction>(Rewrite, MR, +								CDDeclIndirection(*DD, 0), *(rhs_res3.addressof_unary_operator_cptr), *array_subscript_expr_cptr); + +						if (ddcs_ref.has_been_determined_to_be_an_array()) { +							(*cr_shptr).do_replacement(m_state1); +						} else { +							m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); +						} +					} +				} + +				if (ConvertToSCPP && (rhs_res2.ddecl_conversion_state_ptr) && lhs_is_an_indirect_type) { +					for (size_t i = 0; (rhs_res2.indirection_level + i < ddcs_ref.m_indirection_state_stack.size()) +												&& (rhs_res2.indirection_level + i < (*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()); i += 1) { +						{ +							/* Here we're establishing and "enforcing" the constraint that the rhs value must +							 * be of an (array) type that can be assigned to the lhs. */ +							auto cr_shptr = std::make_shared<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0 + i), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); +							auto cr_shptr2 = std::make_shared<CAssignmentTargetConstrainsSourceDynamicArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0 + i), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); + +							if (ddcs_ref.has_been_determined_to_be_an_array(0 + i)) { +								(*cr_shptr).do_replacement(m_state1); +								if (ddcs_ref.has_been_determined_to_be_a_dynamic_array(0 + i)) { +									(*cr_shptr2).do_replacement(m_state1); +								} else { +									m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr2); +								} +							} else { +								m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); +								m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr2); +							} +						} +						{ +							/* Here we're establishing the constraint in the opposite direction as well. */ +							auto cr_shptr = std::make_shared<CAssignmentSourceConstrainsTargetArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i), CDDeclIndirection(*DD, 0 + i)); + +							if ((*(rhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(rhs_res2.indirection_level + i)) { +								(*cr_shptr).do_replacement(m_state1); +							} else { +								m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); +							} +						} +					} +				} + +			}  		}  	} @@ -3119,102 +3362,6 @@ private:  /**********************************************************************************************************************/ -struct CAllocFunctionInfo { -	bool m_seems_to_be_some_kind_of_malloc_or_realloc = false; -	bool m_seems_to_be_some_kind_of_realloc = false; -	clang::CallExpr::const_arg_iterator m_num_bytes_arg_iter; -	std::string m_num_bytes_arg_source_text; -}; -CAllocFunctionInfo analyze_malloc_resemblance(const clang::CallExpr& call_expr, Rewriter &Rewrite) { -	CAllocFunctionInfo retval; - -	auto CE = &call_expr; -	auto function_decl = CE->getDirectCallee(); -	auto num_args = CE->getNumArgs(); -	if (function_decl && ((1 == num_args) || (2 == num_args))) { -		std::string function_name = function_decl->getNameAsString(); -		static const std::string alloc_str = "alloc"; -		static const std::string realloc_str = "realloc"; -		auto lc_function_name = tolowerstr(function_name); -		bool ends_with_alloc = ((lc_function_name.size() >= alloc_str.size()) -				&& (0 == lc_function_name.compare(lc_function_name.size() - alloc_str.size(), alloc_str.size(), alloc_str))); -		bool ends_with_realloc = (ends_with_alloc && (lc_function_name.size() >= realloc_str.size()) -				&& (0 == lc_function_name.compare(lc_function_name.size() - realloc_str.size(), realloc_str.size(), realloc_str))); -		bool still_potentially_valid1 = (ends_with_alloc && (1 == num_args)) || (ends_with_realloc && (2 == num_args)); -		if (still_potentially_valid1) { -			auto arg_iter = CE->arg_begin(); -			if (ends_with_realloc) { -				arg_iter++; -			} -			bool argIsIntegerType = false; -			if (*arg_iter) { -				argIsIntegerType = (*arg_iter)->getType().split().asPair().first->isIntegerType(); -			} -			if (argIsIntegerType) { -				auto arg_source_range = nice_source_range((*arg_iter)->getSourceRange(), Rewrite); -				std::string arg_source_text; -				if (arg_source_range.isValid()) { -					arg_source_text = Rewrite.getRewrittenText(arg_source_range); -					//auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); - -					bool asterisk_found = false; -					auto sizeof_start_index = arg_source_text.find("sizeof("); -					if (std::string::npos != sizeof_start_index) { -						auto sizeof_end_index = arg_source_text.find(")", sizeof_start_index); -						if (std::string::npos != sizeof_end_index) { -							assert(sizeof_end_index > sizeof_start_index); -							std::string before_str = arg_source_text.substr(0, sizeof_start_index); -							std::string after_str; -							if (sizeof_end_index + 1 < arg_source_text.size()) { -								after_str = arg_source_text.substr(sizeof_end_index + 1); -							} - -							auto index = before_str.size() - 1; -							while (0 <= index) { -								if ('*' == before_str[index]) { -									asterisk_found = true; -								} -								if (!std::isspace(before_str[index])) { -									break; -								} - -								index -= 1; -							} -							if (asterisk_found) { -								before_str = before_str.substr(0, index); -							} else { -								size_t index2 = 0; -								while (after_str.size() > index2) { -									if ('*' == after_str[index2]) { -										asterisk_found = true; -									} -									if (!std::isspace(after_str[index2])) { -										break; -									} - -									index2 += 1; -								} -								if (asterisk_found) { -									after_str = after_str.substr(index2 + 1); -								} -							} -						} -					} -					if (true || asterisk_found) { -						retval.m_num_bytes_arg_iter = arg_iter; -						retval.m_seems_to_be_some_kind_of_malloc_or_realloc = true; -						retval.m_num_bytes_arg_source_text = arg_source_text; -						if (ends_with_realloc) { -							retval.m_seems_to_be_some_kind_of_realloc = true; -						} -					} -				} -			} -		} -	} -	return retval; -} -  class MCSSSMalloc2 : public MatchFinder::MatchCallback  {  public: @@ -3594,8 +3741,8 @@ public:  			}  			Expr::NullPointerConstantKind kind = RHS->IgnoreParenCasts()->isNullPointerConstant(*ASTC, Expr::NullPointerConstantValueDependence()); -			if (false && clang::Expr::NPCK_NotNull != kind) { -				if (true) { +			if (clang::Expr::NPCK_NotNull != kind) { +				if (false) {  					{  						if (true) {  							if (true) { @@ -4896,6 +5043,10 @@ public:  					auto fdecl_source_range = nice_source_range(function_decl->getSourceRange(), Rewrite);  					auto fdecl_source_location_str = fdecl_source_range.getBegin().printToString(*MR.SourceManager); +					if (filtered_out_by_location(MR, fdecl_source_range.getBegin())) { +						return void(); +					} +  					for (size_t arg_index = 0; (CE->getNumArgs() > arg_index) && (function_decl->getNumParams() > arg_index); arg_index += 1) {  						auto param_VD = function_decl->getParamDecl(arg_index);  						auto arg_EX = CE->getArg(arg_index); @@ -5859,7 +6010,14 @@ public:  	  Matcher.addMatcher(castExpr(allOf(hasCastKind(CK_ArrayToPointerDecay), unless(hasParent(arraySubscriptExpr())))).bind("mcsssarraytopointerdecay"), &HandlerForSSSArrayToPointerDecay); -	  Matcher.addMatcher(clang::ast_matchers::declaratorDecl().bind("mcsssvardecl"), &HandlerForSSSVarDecl2); +	  //Matcher.addMatcher(clang::ast_matchers::declaratorDecl().bind("mcsssvardecl"), &HandlerForSSSVarDecl2); +	  Matcher.addMatcher(varDecl(anyOf( +	  		hasInitializer(anyOf( +	  				expr(cStyleCastExpr(hasDescendant(declRefExpr().bind("mcsssvardecl5"))).bind("mcsssvardecl3")).bind("mcsssvardecl2"), +	  				expr(hasDescendant(declRefExpr().bind("mcsssvardecl5"))).bind("mcsssvardecl2") +	  				)), +				clang::ast_matchers::anything() +				)).bind("mcsssvardecl"), &HandlerForSSSVarDecl2);  	  Matcher.addMatcher(expr(allOf(  	  		hasParent(expr(anyOf( @@ -6211,15 +6369,16 @@ public:        		}        		if (!(fii_ref.m_legacyhelpers_include_directive_found)) { -      			assert(fii_ref.m_first_include_directive_loc_is_valid); -      			TheRewriter.InsertTextBefore(fii_ref.m_first_include_directive_loc, -      					"#include \"mselegacyhelpers.h\"\n"); -      		} else if (fii_ref.m_first_macro_directive_ptr_is_valid) { -      			TheRewriter.InsertTextAfterToken(fii_ref.m_first_macro_directive_ptr->getLocation(), -      					"#include \"mselegacyhelpers.h\"\n"); -      		} else if (fii_ref.m_beginning_of_file_loc_is_valid) { -      			TheRewriter.InsertTextBefore(fii_ref.m_beginning_of_file_loc, -      					"#include \"mselegacyhelpers.h\"\n"); +      			if (fii_ref.m_first_include_directive_loc_is_valid) { +      				TheRewriter.InsertTextBefore(fii_ref.m_first_include_directive_loc, +      						"\n#include \"mselegacyhelpers.h\"\n"); +      			} else if (fii_ref.m_first_macro_directive_ptr_is_valid) { +      				TheRewriter.InsertTextAfterToken(fii_ref.m_first_macro_directive_ptr->getLocation(), +      						"\n#include \"mselegacyhelpers.h\"\n"); +      			} else if (fii_ref.m_beginning_of_file_loc_is_valid) { +      				TheRewriter.InsertTextBefore(fii_ref.m_beginning_of_file_loc, +      						"\n#include \"mselegacyhelpers.h\"\n"); +      			}        		}        	}        } else { assert(false); } | 
