+end:
+ return ret;
+}
+
+/*
+ * Extract the tracer information necessary to compare versions.
+ * Returns 0 on success, and -1 if the extraction is not successful because the
+ * necessary fields are absents in the trace metadata.
+ */
+static
+int extract_tracer_info(struct ctf_fs_trace *trace,
+ struct tracer_info *current_tracer_info)
+{
+ int ret = 0;
+ struct ctf_trace_class_env_entry *entry;
+
+ /* Clear the current_tracer_info struct */
+ memset(current_tracer_info, 0, sizeof(*current_tracer_info));
+
+ /*
+ * To compare 2 tracer versions, at least the tracer name and it's
+ * major version are needed. If one of these is missing, consider it an
+ * extraction failure.
+ */
+ entry = ctf_trace_class_borrow_env_entry_by_name(
+ trace->metadata->tc, "tracer_name");
+ if (!entry || entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_STR) {
+ goto missing_bare_minimum;
+ }
+
+ /* Set tracer name. */
+ current_tracer_info->name = entry->value.str->str;
+
+ entry = ctf_trace_class_borrow_env_entry_by_name(
+ trace->metadata->tc, "tracer_major");
+ if (!entry || entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
+ goto missing_bare_minimum;
+ }
+
+ /* Set major version number. */
+ current_tracer_info->major = entry->value.i;
+
+ entry = ctf_trace_class_borrow_env_entry_by_name(
+ trace->metadata->tc, "tracer_minor");
+ if (!entry || entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
+ goto end;
+ }
+
+ /* Set minor version number. */
+ current_tracer_info->minor = entry->value.i;
+
+ entry = ctf_trace_class_borrow_env_entry_by_name(
+ trace->metadata->tc, "tracer_patch");
+ if (!entry) {
+ /*
+ * If `tracer_patch` doesn't exist `tracer_patchlevel` might.
+ * For example, `lttng-modules` uses entry name
+ * `tracer_patchlevel`.
+ */
+ entry = ctf_trace_class_borrow_env_entry_by_name(
+ trace->metadata->tc, "tracer_patchlevel");
+ }
+
+ if (!entry || entry->type != CTF_TRACE_CLASS_ENV_ENTRY_TYPE_INT) {
+ goto end;
+ }
+
+ /* Set patch version number. */
+ current_tracer_info->patch = entry->value.i;
+
+ goto end;
+
+missing_bare_minimum:
+ ret = -1;
+end:
+ return ret;
+}
+
+static
+bool is_tracer_affected_by_lttng_event_after_packet_bug(
+ struct tracer_info *curr_tracer_info)
+{
+ bool is_affected = false;
+
+ if (strcmp(curr_tracer_info->name, "lttng-ust") == 0) {
+ if (curr_tracer_info->major < 2) {
+ is_affected = true;
+ } else if (curr_tracer_info->major == 2) {
+ /* fixed in lttng-ust 2.11.0 */
+ if (curr_tracer_info->minor < 11) {
+ is_affected = true;
+ }
+ }
+ } else if (strcmp(curr_tracer_info->name, "lttng-modules") == 0) {
+ if (curr_tracer_info->major < 2) {
+ is_affected = true;
+ } else if (curr_tracer_info->major == 2) {
+ /* fixed in lttng-modules 2.11.0 */
+ if (curr_tracer_info->minor == 10) {
+ /* fixed in lttng-modules 2.10.10 */
+ if (curr_tracer_info->patch < 10) {
+ is_affected = true;
+ }
+ } else if (curr_tracer_info->minor == 9) {
+ /* fixed in lttng-modules 2.9.13 */
+ if (curr_tracer_info->patch < 13) {
+ is_affected = true;
+ }
+ } else if (curr_tracer_info->minor < 9) {
+ is_affected = true;
+ }
+ }
+ }
+
+ return is_affected;
+}
+
+static
+bool is_tracer_affected_by_barectf_event_before_packet_bug(
+ struct tracer_info *curr_tracer_info)
+{
+ bool is_affected = false;
+
+ if (strcmp(curr_tracer_info->name, "barectf") == 0) {
+ if (curr_tracer_info->major < 2) {
+ is_affected = true;
+ } else if (curr_tracer_info->major == 2) {
+ if (curr_tracer_info->minor < 3) {
+ is_affected = true;
+ } else if (curr_tracer_info->minor == 3) {
+ /* fixed in barectf 2.3.1 */
+ if (curr_tracer_info->patch < 1) {
+ is_affected = true;
+ }
+ }