commit c6432d394ee01ce54bac5def39e490a9de261cc3 from: Omar Polo date: Wed Feb 21 12:24:48 2024 UTC iri: rework iri_unparse() I'm not actually pround of the %s%s%s%s%s%s... etc, but it works fine. There's no need to do further escaping here, since consuming code is not supposed to reach inside the iri struct. It'll be made opaque maybe in the future. commit - 62c0f697ddc7396384280f2f8bac7a092700f1ba commit + c6432d394ee01ce54bac5def39e490a9de261cc3 blob - 9a44d9597949d1e4c46f5778bb4d34da0f552753 blob + 1889d871eb431f8caf500fd60d8775627234eb4c --- iri.c +++ iri.c @@ -643,65 +643,35 @@ iri_parse(const char *base, const char *str, struct ir int iri_unparse(const struct iri *i, char *buf, size_t buflen) { - if (buflen == 0) - goto err; - - /* TODO: should %enc octets if needed */ - - buf[0] = '\0'; - - if (i->iri_flags & IH_SCHEME) { - if (strlcat(buf, i->iri_scheme, buflen) >= buflen || - strlcat(buf, ":", buflen) >= buflen) - goto err; - } + int need_ss, have_path, need_s; + int r; - if (i->iri_flags & IH_AUTHORITY) { - if (strlcat(buf, "//", buflen) >= buflen) - goto err; - } - - if (i->iri_flags & IH_UINFO) { - if (strlcat(buf, i->iri_uinfo, buflen) >= buflen || - strlcat(buf, "@", buflen) >= buflen) - goto err; - } - if (i->iri_flags & IH_HOST) { - if (strlcat(buf, i->iri_host, buflen) >= buflen) - goto err; - } - if (i->iri_flags & IH_PORT) { - if (strlcat(buf, ":", buflen) >= buflen || - strlcat(buf, i->iri_portstr, buflen) >= buflen) - goto err; - } + need_ss = (i->iri_flags & IH_AUTHORITY); + have_path = i->iri_flags & IH_PATH; + need_s = have_path && (i->iri_flags & IH_AUTHORITY) && + i->iri_path[0] != '/'; - if (i->iri_flags & IH_PATH) { - if (i->iri_flags & IH_AUTHORITY && - i->iri_path[0] != '/' && - strlcat(buf, "/", buflen) >= buflen) - goto err; - if (strlcat(buf, i->iri_path, buflen) >= buflen) - goto err; + r = snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (i->iri_flags & IH_SCHEME) ? i->iri_scheme : "", + (i->iri_flags & IH_SCHEME) ? ":" : "", + need_ss ? "//" : "", + (i->iri_flags & IH_UINFO) ? i->iri_uinfo : "", + (i->iri_flags & IH_UINFO) ? "@" : "", + (i->iri_flags & IH_HOST) ? i->iri_host : "", + (i->iri_flags & IH_PORT) ? ":" : "", + (i->iri_flags & IH_PORT) ? i->iri_portstr : "", + need_s ? "/" : "", + have_path ? i->iri_path : "", + (i->iri_flags & IH_QUERY) ? "?" : "", + (i->iri_flags & IH_QUERY) ? i->iri_query : "", + (i->iri_flags & IH_FRAGMENT) ? "#" : "", + (i->iri_flags & IH_FRAGMENT) ? i->iri_fragment : ""); + if (r < 0 || (size_t)r >= buflen) { + errno = ENOBUFS; + return (-1); } - if (i->iri_flags & IH_QUERY) { - if (strlcat(buf, "?", buflen) >= buflen || - strlcat(buf, i->iri_query, buflen) >= buflen) - goto err; - } - - if (i->iri_flags & IH_FRAGMENT) { - if (strlcat(buf, "#", buflen) >= buflen || - strlcat(buf, i->iri_fragment, buflen) >= buflen) - goto err; - } - return (0); - - err: - errno = ENOBUFS; - return (-1); } int