@@ -554,322 +554,38 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index,
554554 *index, bound);
555555}
556556
557-
558- /* Instrument array bounds for the pointer array address which is
559- an INDIRECT_REF to the call to .ACCESS_WITH_SIZE. We create special
560- builtin, that gets expanded in the sanopt pass, and make an array
561- dimention of it. POINTER_ADDR is the pointer array's base address.
562- *INDEX is an index to the array.
563- IGNORE_OFF_BY_ONE is true if the POINTER_ADDR is not inside an
564- INDIRECT_REF.
565- Return NULL_TREE if no instrumentation is emitted. */
566-
567- tree
568- ubsan_instrument_bounds_pointer_address (location_t loc, tree pointer_addr,
569- tree *index,
570- bool ignore_off_by_one)
571- {
572- gcc_assert (TREE_CODE (pointer_addr) == INDIRECT_REF);
573- tree call = TREE_OPERAND (pointer_addr, 0 );
574- if (!is_access_with_size_p (call))
575- return NULL_TREE;
576- tree bound = get_bound_from_access_with_size (call);
577-
578- if (ignore_off_by_one)
579- bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound,
580- build_int_cst (TREE_TYPE (bound),
581- 1 ));
582-
583- /* Don't emit instrumentation in the most common cases. */
584- tree idx = NULL_TREE;
585- if (TREE_CODE (*index) == INTEGER_CST)
586- idx = *index;
587- else if (TREE_CODE (*index) == BIT_AND_EXPR
588- && TREE_CODE (TREE_OPERAND (*index, 1 )) == INTEGER_CST)
589- idx = TREE_OPERAND (*index, 1 );
590- if (idx
591- && TREE_CODE (bound) == INTEGER_CST
592- && tree_int_cst_sgn (idx) >= 0
593- && tree_int_cst_lt (idx, bound))
594- return NULL_TREE;
595-
596- *index = save_expr (*index);
597-
598- /* Create an array_type for the corresponding pointer array. */
599- tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
600- /* The array's element type can be get from the return type of the call to
601- .ACCESS_WITH_SIZE. */
602- tree element_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call)));
603- tree array_type = build_array_type (element_type, itype);
604- /* Create a "(T *) 0" tree node to describe the array type. */
605- tree zero_with_type = build_int_cst (build_pointer_type (array_type), 0 );
606- return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS,
607- void_type_node, 3 , zero_with_type,
608- *index, bound);
609- }
610-
611- /* This structure is to combine a factor with its parent and its position
612- * in its parent tree. */
613- struct factor_t
614- {
615- tree factor;
616- tree parent; /* the parent tree of this factor. */
617- int pos; /* the position of this factor in its parent tree. */
618- };
619-
620- /* for a multiply expression like:
621- ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4
622-
623- locate all the factors, the parents of the factor and the position of
624- the factor in its parent, and put them to VEC_FACTORS. */
625-
626- static void
627- get_factors_from_mul_expr (tree mult_expr, tree parent,
628- int pos, auto_vec<factor_t > *vec_factors)
629- {
630- struct factor_t mult_factor = {0 , 0 , -1 };
631- mult_factor.factor = mult_expr;
632- mult_factor.parent = parent;
633- mult_factor.pos = pos;
634-
635- while (CONVERT_EXPR_CODE_P (TREE_CODE (mult_expr)))
636- {
637- mult_factor.parent = mult_expr;
638- mult_factor.pos = 0 ;
639- mult_expr = TREE_OPERAND (mult_expr, 0 );
640- mult_factor.factor = mult_expr;
641- }
642- if (TREE_CODE (mult_expr) != MULT_EXPR)
643- vec_factors->safe_push (mult_factor);
644- else
645- {
646- get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 0 ), mult_expr,
647- 0 , vec_factors);
648- get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 1 ), mult_expr,
649- 1 , vec_factors);
650- }
651- }
652-
653- /* Given an OFFSET expression, and the ELEMENT_SIZE,
654- get the index expression from OFFSET and return it.
655- For example:
656- OFFSET:
657- ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4
658- ELEMENT_SIZE:
659- (sizetype) SAVE_EXPR <n> * 4
660- get the index as (long unsigned int) m, and return it.
661- The INDEX_P holds the pointer to the parent tree of the index,
662- INDEX_N holds the position of the index in its parent. */
663-
664- static tree
665- get_index_from_offset (tree offset, tree *index_p,
666- int *index_n, tree element_size)
667- {
668- if (TREE_CODE (offset) != MULT_EXPR)
669- return NULL_TREE;
670-
671- auto_vec<factor_t > e_factors, o_factors;
672- get_factors_from_mul_expr (element_size, NULL , -1 , &e_factors);
673- get_factors_from_mul_expr (offset, *index_p, *index_n, &o_factors);
674-
675- if (e_factors.is_empty () || o_factors.is_empty ())
676- return NULL_TREE;
677-
678- bool all_found = true ;
679- for (unsigned i = 0 ; i < e_factors.length (); i++)
680- {
681- factor_t e_size_factor = e_factors[i];
682- bool found = false ;
683- for (unsigned j = 0 ; j < o_factors.length ();)
684- {
685- factor_t o_exp_factor = o_factors[j];
686- if (operand_equal_p (e_size_factor.factor , o_exp_factor.factor ))
687- {
688- o_factors.unordered_remove (j);
689- found = true ;
690- break ;
691- }
692- else
693- j++;
694- }
695- if (!found)
696- all_found = false ;
697- }
698-
699- if (!all_found)
700- return NULL_TREE;
701-
702- if (o_factors.length () != 1 )
703- return NULL_TREE;
704-
705- *index_p = o_factors[0 ].parent ;
706- *index_n = o_factors[0 ].pos ;
707- return o_factors[0 ].factor ;
708- }
709-
710- /* For an pointer + offset computation expression, such as,
711- *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
712- + (sizetype) ((long unsigned int) index * 4
713- Return the index of this pointer array reference,
714- set the parent tree of INDEX to *INDEX_P.
715- set the operand position of the INDEX in the parent tree to *INDEX_N.
716- If failed, return NULL_TREE. */
717-
718- static tree
719- get_index_from_pointer_addr_expr (tree pointer, tree *index_p, int *index_n)
720- {
721- *index_p = NULL_TREE;
722- *index_n = -1 ;
723- if (TREE_CODE (TREE_OPERAND (pointer, 0 )) != INDIRECT_REF)
724- return NULL_TREE;
725- tree call = TREE_OPERAND (TREE_OPERAND (pointer, 0 ), 0 );
726- if (!is_access_with_size_p (call))
727- return NULL_TREE;
728-
729- /* Get the pointee type of the call to .ACCESS_WITH_SIZE.
730- This should be the element type of the pointer array. */
731- tree pointee_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call)));
732- tree pointee_size = TYPE_SIZE_UNIT (pointee_type);
733-
734- tree index_exp = TREE_OPERAND (pointer, 1 );
735- *index_p = pointer;
736- *index_n = 1 ;
737-
738- if (!(TREE_CODE (index_exp) != MULT_EXPR
739- && tree_int_cst_equal (pointee_size, integer_one_node)))
740- {
741- while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp)))
742- {
743- *index_p = index_exp;
744- *index_n = 0 ;
745- index_exp = TREE_OPERAND (index_exp, 0 );
746- }
747- index_exp = get_index_from_offset (index_exp, index_p,
748- index_n, pointee_size);
749-
750- if (!index_exp)
751- return NULL_TREE;
752- }
753-
754- while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp)))
755- {
756- *index_p = index_exp;
757- *index_n = 0 ;
758- index_exp = TREE_OPERAND (index_exp, 0 );
759- }
760-
761- return index_exp;
762- }
763-
764- /* Return TRUE when the EXPR is a pointer array address that could be
765- instrumented.
766- We only instrument an address computation similar as the following:
767- *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
768- + (sizetype) ((long unsigned int) index * 4)
769- if the EXPR is instrumentable, return TRUE and
770- set the index to *INDEX.
771- set the *.ACCESS_WITH_SIZE to *BASE.
772- set the parent tree of INDEX to *INDEX_P.
773- set the operand position of the INDEX in the parent tree to INDEX_N. */
774-
775- static bool
776- is_instrumentable_pointer_array_address (tree expr, tree *base,
777- tree *index, tree *index_p,
778- int *index_n)
779- {
780- /* For a poiner array address as:
781- (*.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B)
782- + (sizetype) ((long unsigned int) index * 4)
783- op0 is the call to *.ACCESS_WITH_SIZE;
784- op1 is the index. */
785- if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
786- return false ;
787-
788- tree op0 = TREE_OPERAND (expr, 0 );
789- if (TREE_CODE (op0) != INDIRECT_REF)
790- return false ;
791- if (!is_access_with_size_p (TREE_OPERAND (op0, 0 )))
792- return false ;
793- tree op1 = get_index_from_pointer_addr_expr (expr, index_p, index_n);
794- if (op1 != NULL_TREE)
795- {
796- *base = op0;
797- *index = op1;
798- return true ;
799- }
800- return false ;
801- }
802-
803- /* Return true iff T is an array or an indirect reference that was
804- instrumented by SANITIZE_BOUNDS. */
557+ /* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */
805558
806559bool
807- ubsan_array_ref_instrumented_p (tree t)
560+ ubsan_array_ref_instrumented_p (const_tree t)
808561{
809- if (TREE_CODE (t) != ARRAY_REF
810- && TREE_CODE (t) != MEM_REF)
562+ if (TREE_CODE (t) != ARRAY_REF)
811563 return false ;
812564
813- bool is_array = (TREE_CODE (t) == ARRAY_REF);
814- tree op0 = NULL_TREE;
815- tree op1 = NULL_TREE;
816- tree index_p = NULL_TREE;
817- int index_n = 0 ;
818- if (is_array)
819- {
820- op1 = TREE_OPERAND (t, 1 );
821- return TREE_CODE (op1) == COMPOUND_EXPR
822- && TREE_CODE (TREE_OPERAND (op1, 0 )) == CALL_EXPR
823- && CALL_EXPR_FN (TREE_OPERAND (op1, 0 )) == NULL_TREE
824- && CALL_EXPR_IFN (TREE_OPERAND (op1, 0 )) == IFN_UBSAN_BOUNDS;
825- }
826- else if (is_instrumentable_pointer_array_address (t, &op0, &op1,
827- &index_p, &index_n))
828- return TREE_CODE (op1) == COMPOUND_EXPR
829- && TREE_CODE (TREE_OPERAND (op1, 0 )) == CALL_EXPR
830- && CALL_EXPR_FN (TREE_OPERAND (op1, 0 )) == NULL_TREE
831- && CALL_EXPR_IFN (TREE_OPERAND (op1, 0 )) == IFN_UBSAN_BOUNDS;
832-
833- return false ;
565+ tree op1 = TREE_OPERAND (t, 1 );
566+ return TREE_CODE (op1) == COMPOUND_EXPR
567+ && TREE_CODE (TREE_OPERAND (op1, 0 )) == CALL_EXPR
568+ && CALL_EXPR_FN (TREE_OPERAND (op1, 0 )) == NULL_TREE
569+ && CALL_EXPR_IFN (TREE_OPERAND (op1, 0 )) == IFN_UBSAN_BOUNDS;
834570}
835571
836- /* Instrument an ARRAY_REF or an address computation whose base address is
837- a call to .ACCESS_WITH_SIZE, if it hasn't already been instrumented.
838- IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR, or the
839- address computation is not inside a INDIRECT_REF. */
572+ /* Instrument an ARRAY_REF, if it hasn't already been instrumented.
573+ IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
840574
841575void
842576ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one)
843577{
844- tree e = NULL_TREE;
845- tree op0 = NULL_TREE;
846- tree op1 = NULL_TREE;
847- tree index_p = NULL_TREE; /* the parent tree of INDEX. */
848- int index_n = 0 ; /* the operand position of INDEX in the parent tree. */
849-
850578 if (!ubsan_array_ref_instrumented_p (*expr_p)
851579 && sanitize_flags_p (SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT)
852580 && current_function_decl != NULL_TREE)
853581 {
854- if (TREE_CODE (*expr_p) == ARRAY_REF)
855- {
856- op0 = TREE_OPERAND (*expr_p, 0 );
857- op1 = TREE_OPERAND (*expr_p, 1 );
858- index_p = *expr_p;
859- index_n = 1 ;
860- e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0,
861- &op1, ignore_off_by_one);
862- }
863- else if (is_instrumentable_pointer_array_address (*expr_p, &op0, &op1,
864- &index_p, &index_n))
865- e = ubsan_instrument_bounds_pointer_address (EXPR_LOCATION (*expr_p),
866- op0, &op1,
867- ignore_off_by_one);
868-
869- /* Replace the original INDEX with the instrumented INDEX. */
582+ tree op0 = TREE_OPERAND (*expr_p, 0 );
583+ tree op1 = TREE_OPERAND (*expr_p, 1 );
584+ tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, &op1,
585+ ignore_off_by_one);
870586 if (e != NULL_TREE)
871- TREE_OPERAND (index_p, index_n)
872- = build2 (COMPOUND_EXPR, TREE_TYPE (op1), e, op1);
587+ TREE_OPERAND (*expr_p, 1 ) = build2 (COMPOUND_EXPR, TREE_TYPE (op1),
588+ e, op1);
873589 }
874590}
875591
0 commit comments