On Fri, 5 Jul 2024 at 16:37, Alex Bennée <alex.ben...@linaro.org> wrote:
>
> From: Gustavo Romero <gustavo.rom...@linaro.org>
>
> This commit implements the stubs to handle the qIsAddressTagged,
> qMemTag, and QMemTag GDB packets, allowing all GDB 'memory-tag'
> subcommands to work with QEMU gdbstub on aarch64 user mode. It also
> implements the get/set functions for the special GDB MTE register
> 'tag_ctl', used to control the MTE fault type at runtime.
>
> Signed-off-by: Gustavo Romero <gustavo.rom...@linaro.org>
> Message-Id: <20240628050850.536447-11-gustavo.rom...@linaro.org>
> Signed-off-by: Alex Bennée <alex.ben...@linaro.org>
> Message-Id: <20240705084047.857176-40-alex.ben...@linaro.org>

Hi; Coverity thinks there's a memory leak in this function
(CID 1549757):

> +void arm_cpu_register_gdb_commands(ARMCPU *cpu)
> +{
> +    GArray *query_table =
> +        g_array_new(FALSE, FALSE, sizeof(GdbCmdParseEntry));
> +    GArray *set_table =
> +        g_array_new(FALSE, FALSE, sizeof(GdbCmdParseEntry));
> +    GString *qsupported_features = g_string_new(NULL);

We allocate memory for the qsupported_features GString here, but
it looks like nowhere in the function either passes it to
some other function that takes ownership of it, and we don't
free it either.

> +    if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
> +    #ifdef TARGET_AARCH64
> +        aarch64_cpu_register_gdb_commands(cpu, qsupported_features, 
> query_table,
> +                                          set_table);
> +    #endif

(PS: this ifdef/endif ought to be on the left margin, not indented.)

> +    }
> +
> +    /* Set arch-specific handlers for 'q' commands. */
> +    if (query_table->len) {
> +        gdb_extend_query_table(&g_array_index(query_table,
> +                                              GdbCmdParseEntry, 0),
> +                                              query_table->len);
> +    }
> +
> +    /* Set arch-specific handlers for 'Q' commands. */
> +    if (set_table->len) {
> +        gdb_extend_set_table(&g_array_index(set_table,
> +                             GdbCmdParseEntry, 0),
> +                             set_table->len);
> +    }
> +
> +    /* Set arch-specific qSupported feature. */
> +    if (qsupported_features->len) {
> +        gdb_extend_qsupported_features(qsupported_features->str);
> +    }
> +}

Something odd also seems to be happening with the query_table
and set_table -- we allocate them in this function, and we
rely on the memory not going away because we pass pointers
into the actual array data into gdb_extend_query_table()
and gdb_extend_set_table() which those functions retain copies
of, but we don't keep hold of the pointer to the struct GArray
itself.

The functions gdb_extend_set_table() and gdb_extend_query_table()
both seem to not quite do what their documentation says they
do. The docs say they extend the set table and the query table,
but the implementation appears to be setting an extended set
table/query table (e.g. you can't extend the table twice).

Perhaps a more natural API would be for these functions to
either:
 * be passed in the entire GArray, and take ownership of
   it and be responsible for disposing of it
 * take a copy of the entries they're passed in, so that
   the calling function can free the GArray and its
   contents after the call
?

thanks
-- PMM

Reply via email to