From 7cc777b733128024e481e947bb72a4aeb0755b9b Mon Sep 17 00:00:00 2001 From: Marko Kreen Date: Tue, 4 May 2010 16:56:33 +0300 Subject: [PATCH] Removes fixed-length limit from parameter values. --- include/bouncer.h | 1 + include/varcache.h | 16 ++++---- src/admin.c | 12 ++++-- src/janitor.c | 1 + src/objects.c | 2 + src/varcache.c | 96 ++++++++++++++++++++++++++-------------------- 6 files changed, 74 insertions(+), 54 deletions(-) diff --git a/include/bouncer.h b/include/bouncer.h index 7747a56..a6ab8c7 100644 --- a/include/bouncer.h +++ b/include/bouncer.h @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef DBGVER #define FULLVER PACKAGE_NAME " version " PACKAGE_VERSION " (" DBGVER ")" diff --git a/include/varcache.h b/include/varcache.h index 1cf4821..b9004bf 100644 --- a/include/varcache.h +++ b/include/varcache.h @@ -1,16 +1,16 @@ -#define VAR_ENCODING_LEN 16 -#define VAR_DATESTYLE_LEN 32 -#define VAR_TIMEZONE_LEN 36 -#define VAR_STDSTR_LEN 4 +enum VarCacheIdx { + VDateStyle = 0, + VClientEncoding, + VTimeZone, + VStdStr, + NumVars +}; typedef struct VarCache VarCache; struct VarCache { - char client_encoding[VAR_ENCODING_LEN]; - char datestyle[VAR_DATESTYLE_LEN]; - char timezone[VAR_TIMEZONE_LEN]; - char std_strings[VAR_STDSTR_LEN]; + struct PStr *var_list[NumVars]; }; bool varcache_set(VarCache *cache, const char *key, const char *value) /* _MUSTCHECK */; diff --git a/src/admin.c b/src/admin.c index 8cb896a..7940493 100644 --- a/src/admin.c +++ b/src/admin.c @@ -286,6 +286,10 @@ static bool show_one_fd(PgSocket *admin, PgSocket *sk) struct MBuf tmp; VarCache *v = &sk->vars; uint64_t ckey; + const struct PStr *client_encoding = v->var_list[VClientEncoding]; + const struct PStr *std_strings = v->var_list[VStdStr]; + const struct PStr *datestyle = v->var_list[VDateStyle]; + const struct PStr *timezone = v->var_list[VTimeZone]; mbuf_init_fixed_reader(&tmp, sk->cancel_key, 8); if (!mbuf_get_uint64be(&tmp, &ckey)) @@ -299,10 +303,10 @@ static bool show_one_fd(PgSocket *admin, PgSocket *sk) addr->port, ckey, sk->link ? sbuf_socket(&sk->link->sbuf) : 0, - v->client_encoding[0] ? v->client_encoding : NULL, - v->std_strings[0] ? v->std_strings : NULL, - v->datestyle[0] ? v->datestyle : NULL, - v->timezone[0] ? v->timezone : NULL); + client_encoding ? client_encoding->str : NULL, + std_strings ? std_strings->str : NULL, + datestyle ? datestyle->str : NULL, + timezone ? timezone->str : NULL); } /* send a row with sendmsg, optionally attaching a fd */ diff --git a/src/janitor.c b/src/janitor.c index 40ffb56..409167d 100644 --- a/src/janitor.c +++ b/src/janitor.c @@ -578,6 +578,7 @@ static void kill_pool(PgPool *pool) list_del(&pool->map_head); statlist_remove(&pool_list, &pool->head); + varcache_clean(&pool->orig_vars); slab_free(pool_cache, pool); } diff --git a/src/objects.c b/src/objects.c index 966ca0a..6251ef7 100644 --- a/src/objects.c +++ b/src/objects.c @@ -153,6 +153,7 @@ void change_client_state(PgSocket *client, SocketState newstate) /* put to new location */ switch (client->state) { case CL_FREE: + varcache_clean(&client->vars); slab_free(client_cache, client); break; case CL_JUSTFREE: @@ -211,6 +212,7 @@ void change_server_state(PgSocket *server, SocketState newstate) /* put to new location */ switch (server->state) { case SV_FREE: + varcache_clean(&server->vars); slab_free(server_cache, server); break; case SV_JUSTFREE: diff --git a/src/varcache.c b/src/varcache.c index d6f54f9..ce3fc8e 100644 --- a/src/varcache.c +++ b/src/varcache.c @@ -24,54 +24,62 @@ struct var_lookup { const char *name; - int offset; - int len; + enum VarCacheIdx idx; }; static const struct var_lookup lookup [] = { - {"client_encoding", offsetof(VarCache, client_encoding), VAR_ENCODING_LEN }, - {"datestyle", offsetof(VarCache, datestyle), VAR_DATESTYLE_LEN }, - {"timezone", offsetof(VarCache, timezone), VAR_TIMEZONE_LEN }, - {"standard_conforming_strings", offsetof(VarCache, std_strings), VAR_STDSTR_LEN }, + {"client_encoding", VClientEncoding }, + {"datestyle", VDateStyle }, + {"timezone", VTimeZone }, + {"standard_conforming_strings", VStdStr }, {NULL}, }; -static inline char *get_value(VarCache *cache, const struct var_lookup *lk) +static struct StrPool *vpool; + +static inline struct PStr *get_value(VarCache *cache, const struct var_lookup *lk) { - return (char *)(cache) + lk->offset; + return cache->var_list[lk->idx]; } bool varcache_set(VarCache *cache, const char *key, const char *value) { - int vlen; - char *pos; const struct var_lookup *lk; + struct PStr *pstr = NULL; - /* convert NULL to empty string */ - if (value == NULL) - value = ""; - - for (lk = lookup; lk->name; lk++) { - if (strcasecmp(lk->name, key) != 0) - continue; - - vlen = strlen(value); - if (vlen >= lk->len) { - log_warning("varcache_set overflow: %s", key); + if (!vpool) { + vpool = strpool_create(); + if (!vpool) return false; - } + } - pos = get_value(cache, lk); - memcpy(pos, value, vlen + 1); - return true; + for (lk = lookup; lk->name; lk++) { + if (strcasecmp(lk->name, key) == 0) + goto set_value; } return false; + +set_value: + /* drop old value */ + strpool_decref(cache->var_list[lk->idx]); + cache->var_list[lk->idx] = NULL; + + /* ignore empty value */ + if (!value && !value[0]) + return false; + + /* set new value */ + pstr = strpool_get(vpool, value, strlen(value)); + if (!pstr) + return false; + cache->var_list[lk->idx] = pstr; + return true; } static bool is_std_quote(VarCache *vars) { - const char *val = vars->std_strings; - return strcasecmp(val, "on") == 0; + const struct PStr *s = vars->var_list[VStdStr]; + return s && strcasecmp(s->str, "on") == 0; } static bool quote_literal(char *buf, int buflen, const char *src, bool std_quote) @@ -134,7 +142,7 @@ bool varcache_apply(PgSocket *server, PgSocket *client, bool *changes_p) PktBuf pkt; uint8_t buf[STARTUP_BUF]; int changes = 0; - const char *cval, *sval; + struct PStr *cval, *sval; const struct var_lookup *lk; uint8_t *debug_sql; bool std_quote = is_std_quote(&server->vars); @@ -148,7 +156,8 @@ bool varcache_apply(PgSocket *server, PgSocket *client, bool *changes_p) for (lk = lookup; lk->name; lk++) { sval = get_value(&server->vars, lk); cval = get_value(&client->vars, lk); - changes += apply_var(&pkt, lk->name, cval, sval, std_quote); + if (cval) + changes += apply_var(&pkt, lk->name, cval->str, sval->str, std_quote); } *changes_p = changes > 0; if (!changes) @@ -163,32 +172,35 @@ bool varcache_apply(PgSocket *server, PgSocket *client, bool *changes_p) void varcache_fill_unset(VarCache *src, PgSocket *dst) { - char *srcval, *dstval; + struct PStr *srcval, *dstval; const struct var_lookup *lk; for (lk = lookup; lk->name; lk++) { - srcval = get_value(src, lk); - dstval = get_value(&dst->vars, lk); - if (!*dstval) - memcpy(dstval, srcval, lk->len); + srcval = src->var_list[lk->idx]; + dstval = dst->vars.var_list[lk->idx]; + if (!dstval) { + strpool_incref(srcval); + dst->vars.var_list[lk->idx] = srcval; + } } } void varcache_clean(VarCache *cache) { - cache->client_encoding[0] = 0; - cache->datestyle[0] = 0; - cache->timezone[0] = 0; - cache->std_strings[0] = 0; + int i; + for (i = 0; i < NumVars; i++) { + strpool_decref(cache->var_list[i]); + cache->var_list[i] = NULL; + } } void varcache_add_params(PktBuf *pkt, VarCache *vars) { - char *val; + struct PStr *val; const struct var_lookup *lk; for (lk = lookup; lk->name; lk++) { - val = get_value(vars, lk); - if (*val) - pktbuf_write_ParameterStatus(pkt, lk->name, val); + val = vars->var_list[lk->idx]; + if (val) + pktbuf_write_ParameterStatus(pkt, lk->name, val->str); } } -- 2.40.0