Repository: valkey-io/valkey
File: src/networking.c (C)

Code before:
        return -1;
}

char *getClientTypeName(int class) {
    switch (class) {
    case CLIENT_TYPE_NORMAL: return "normal";
    case CLIENT_TYPE_REPLICA: return "slave";
    case CLIENT_TYPE_PUBSUB: return "pubsub";
    case CLIENT_TYPE_PRIMARY: return "master";
    default: return NULL;
    }
}

/* The function checks if the client reached output buffer soft or hard
 * limit, and also update the state needed to check the soft limit as
 * a side effect.
 *
 * Return value: non-zero if the client reached the soft or the hard limit.
 *               Otherwise zero is returned. */
int checkClientOutputBufferLimits(client *c) {
    int soft = 0, hard = 0, class;
    unsigned long used_mem = getClientOutputBufferMemoryUsage(c);

    /* For unauthenticated clients which were also never authenticated before the output buffer is limited to prevent
     * them from abusing it by not reading the replies */
    if (used_mem > REPLY_BUFFER_SIZE_UNAUTHENTICATED_CLIENT  && authRequired(c) && !clientEverAuthenticated(c))
        return 1;

    class = getClientType(c);
    /* For the purpose of output buffer limiting, primaries are handled
     * like normal clients. */
    if (class == CLIENT_TYPE_PRIMARY) class = CLIENT_TYPE_NORMAL;

    /* Note that it doesn't make sense to set the replica clients output buffer
     * limit lower than the repl-backlog-size config (partial sync will succeed
     * and then replica will get disconnected).
     * Such a configuration is ignored (the size of repl-backlog-size will be used).
     * This doesn't have memory consumption implications since the replica client
     * will share the backlog buffers memory. */
    size_t hard_limit_bytes = server.client_obuf_limits[class].hard_limit_bytes;
    if (class == CLIENT_TYPE_REPLICA && hard_limit_bytes && (long long)hard_limit_bytes < server.repl_backlog_size)
        hard_limit_bytes = server.repl_backlog_size;
    if (server.client_obuf_limits[class].hard_limit_bytes && used_mem >= hard_limit_bytes) hard = 1;
    if (server.client_obuf_limits[class].soft_limit_bytes &&
        used_mem >= server.client_obuf_limits[class].soft_limit_bytes)
        soft = 1;

    /* We need to check if the soft limit is reached continuously for the
     * specified amount of seconds. */
    if (soft) {
        if (c->obuf_soft_limit_reached_time == 0) {

Review comment (security):
Make clang-format happy

```suggestion
    if (used_mem > REPLY_BUFFER_SIZE_UNAUTHENTICATED_CLIENT && authRequired(c) && !clientEverAuthenticated(c))
```

Code after:
    }
    return usage;
}

/* Returns the total client's memory usage.
 * Optionally, if output_buffer_mem_usage is not NULL, it fills it with
 * the client output buffer memory usage portion of the total. */
size_t getClientMemoryUsage(client *c, size_t *output_buffer_mem_usage) {
    size_t mem = getClientOutputBufferMemoryUsage(c);

    if (output_buffer_mem_usage != NULL) *output_buffer_mem_usage = mem;
    mem += c->querybuf ? sdsAllocSize(c->querybuf) : 0;
    mem += zmalloc_size(c);
    mem += c->buf_usable_size;
    /* For efficiency (less work keeping track of the argv memory), it doesn't include the used memory
     * i.e. unused sds space and internal fragmentation, just the string length. but this is enough to
     * spot problematic clients. */
    mem += c->argv_len_sum + sizeof(robj *) * c->argc;
    mem += multiStateMemOverhead(c);

    /* Add memory overhead of pubsub channels and patterns. Note: this is just the overhead of the robj pointers
     * to the strings themselves because they aren't stored per client. */
    mem += pubsubMemOverhead(c);

    /* Add memory overhead of the tracking prefixes, this is an underestimation so we don't need to traverse the entire
     * rax */
    if (c->pubsub_data && c->pubsub_data->client_tracking_prefixes)
        mem += c->pubsub_data->client_tracking_prefixes->numnodes * (sizeof(raxNode) * sizeof(raxNode *));

    return mem;
}

/* Get the class of a client, used in order to enforce limits to different
 * classes of clients.
 *
 * The function will return one of the following:
 * CLIENT_TYPE_NORMAL -> Normal client, including MONITOR
 * CLIENT_TYPE_REPLICA  -> replica
 * CLIENT_TYPE_PUBSUB -> Client subscribed to Pub/Sub channels
 * CLIENT_TYPE_PRIMARY -> The client representing our replication primary.
 */
int getClientType(client *c) {
    if (c->flag.primary) return CLIENT_TYPE_PRIMARY;
    /* Even though MONITOR clients are marked as replicas, we
     * want the expose them as normal clients. */
    if (c->flag.replica && !c->flag.monitor) return CLIENT_TYPE_REPLICA;
    if (c->flag.pubsub) return CLIENT_TYPE_PUBSUB;
    return CLIENT_TYPE_NORMAL;
}

int getClientTypeByName(char *name) {