target/armv7m,cortex_m: introduce checked arch_info cast routines
authorTomas Vanek <vanekt@fbl.cz>
Wed, 24 Nov 2021 21:11:13 +0000 (22:11 +0100)
committerTomas Vanek <vanekt@fbl.cz>
Fri, 25 Feb 2022 19:56:41 +0000 (19:56 +0000)
target_to_armv7m() and target_to_cm() do not match the magic number
so they are not suitable for use outside of target driver code.

Add checked versions of pointer getters. Match the magic number
to ensure the returned value points to struct of the correct type.

Change-Id: If90ef7e969ef04f0f2103e0da29dcbe8e1ac1c0d
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/6750
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/target/armv7m.h
src/target/cortex_m.h

index d33e574928b6e071c18df1645965210b0ed41f1f..9ac121ac316be0a058132b6252bb658c91c4281d 100644 (file)
@@ -255,15 +255,48 @@ struct armv7m_common {
        void (*pre_restore_context)(struct target *target);
 };
 
+static inline bool is_armv7m(const struct armv7m_common *armv7m)
+{
+       return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
+}
+
+/**
+ * @returns the pointer to the target specific struct
+ * without matching a magic number.
+ * Use in target specific service routines, where the correct
+ * type of arch_info is certain.
+ */
 static inline struct armv7m_common *
 target_to_armv7m(struct target *target)
 {
        return container_of(target->arch_info, struct armv7m_common, arm);
 }
 
-static inline bool is_armv7m(const struct armv7m_common *armv7m)
+/**
+ * @returns the pointer to the target specific struct
+ * or NULL if the magic number does not match.
+ * Use in a flash driver or any place where mismatch of the arch_info
+ * type can happen.
+ */
+static inline struct armv7m_common *
+target_to_armv7m_safe(struct target *target)
 {
-       return armv7m->common_magic == ARMV7M_COMMON_MAGIC;
+       if (!target)
+               return NULL;
+
+       if (!target->arch_info)
+               return NULL;
+
+       /* Check the parent type first to prevent peeking memory too far
+        * from arch_info pointer */
+       if (!is_arm(target_to_arm(target)))
+               return NULL;
+
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       if (!is_armv7m(armv7m))
+               return NULL;
+
+       return armv7m;
 }
 
 struct armv7m_algorithm {
index cabe405ce1c99b3a6b771b26048937514c85bc6d..8fb34f46c12fa2ce49b4aeb4cf98c370f8a2461d 100644 (file)
@@ -247,13 +247,6 @@ struct cortex_m_common {
        bool maskints_erratum;
 };
 
-static inline struct cortex_m_common *
-target_to_cm(struct target *target)
-{
-       return container_of(target->arch_info,
-                       struct cortex_m_common, armv7m.arm);
-}
-
 static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m)
 {
        return cortex_m->common_magic == CORTEX_M_COMMON_MAGIC;
@@ -267,6 +260,40 @@ static inline bool is_cortex_m_with_dap_access(const struct cortex_m_common *cor
        return !cortex_m->armv7m.is_hla_target;
 }
 
+/**
+ * @returns the pointer to the target specific struct
+ * without matching a magic number.
+ * Use in target specific service routines, where the correct
+ * type of arch_info is certain.
+ */
+static inline struct cortex_m_common *
+target_to_cm(struct target *target)
+{
+       return container_of(target->arch_info,
+                       struct cortex_m_common, armv7m.arm);
+}
+
+/**
+ * @returns the pointer to the target specific struct
+ * or NULL if the magic number does not match.
+ * Use in a flash driver or any place where mismatch of the arch_info
+ * type can happen.
+ */
+static inline struct cortex_m_common *
+target_to_cortex_m_safe(struct target *target)
+{
+       /* Check the parent types first to prevent peeking memory too far
+        * from arch_info pointer */
+       if (!target_to_armv7m_safe(target))
+               return NULL;
+
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       if (!is_cortex_m_or_hla(cortex_m))
+               return NULL;
+
+       return cortex_m;
+}
+
 int cortex_m_examine(struct target *target);
 int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint);
 int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint);