Mg_mk_str function assigns stack memory address

#1

While debugging an unrelated issue, I came across the mg_mk_str function. I see it being called in mg_connect_http_base as:

  if (mg_parse_uri(mg_mk_str(url), &scheme, user_info, host, &port_i, path,
               &query, &fragment) != 0) {
    MG_SET_PTRPTR(opts.error_string, "cannot parse url");
    goto out;
 }

mg_parse_uri takes mg_str pointers, and doesn’t back them with memory, rather it just sets the ->p pointers to difference segments of the newly created mg_str url returned by mg_mk_str.

However, looking at the definition for mg_mk_str, we see:

struct mg_str mg_mk_str(const char *s) WEAK;
struct mg_str mg_mk_str(const char *s) {
  struct mg_str ret = {s, 0};
  if (s != NULL) ret.len = strlen(s);
  return ret;
}

The variable ret was created as a local variable, and its memory address is being returned!! Am I missing something here? The fact that there is a WEAK tag on the prototype above it leads me to believe that there is a platform specific definition somewhere, but even if thats the case, the default is highly unsafe.

Is this a bug?

Cheers,

Stephen

#2

mg_mk_str returns a struct mg_str, not a struct mg_str* so the function does not return a stack address.

When a function returns a struct, the compiler pushes a “hidden” pointer to the result structure.
It can be seen like this:

void mg_mk_str(const char *s, struct mg_str *result) {
  struct mg_str ret = {s, 0};
  if (s != NULL) ret.len = strlen(s);
  *result = ret;
}
1 Like
#3

Interesting, I had always treated it as though it was an array declaration, where omitting the brackets evaluated as the memory address of the first item.

Thank you for the response and sample code