@@ -58,7 +58,7 @@ struct ap_socache_instance_t {
5858 const char * servers ;
5959 apr_memcache_t * mc ;
6060 const char * tag ;
61- apr_size_t taglen ;
61+ apr_size_t taglen ; /* strlen(tag) + 1 */
6262};
6363
6464static const char * socache_mc_create (ap_socache_instance_t * * context ,
@@ -69,6 +69,10 @@ static const char *socache_mc_create(ap_socache_instance_t **context,
6969
7070 * context = ctx = apr_palloc (p , sizeof * ctx );
7171
72+ if (!arg || !* arg ) {
73+ return "List of server names required to create memcache socache." ;
74+ }
75+
7276 ctx -> servers = apr_pstrdup (p , arg );
7377
7478 return NULL ;
@@ -157,7 +161,10 @@ static apr_status_t socache_mc_init(ap_socache_instance_t *ctx,
157161 }
158162
159163 ctx -> tag = apr_pstrcat (p , namespace , ":" , NULL );
160- ctx -> taglen = strlen (ctx -> tag );
164+ ctx -> taglen = strlen (ctx -> tag ) + 1 ;
165+
166+ /* socache API constraint: */
167+ AP_DEBUG_ASSERT (ctx -> taglen <= 16 );
161168
162169 return APR_SUCCESS ;
163170}
@@ -167,21 +174,28 @@ static void socache_mc_kill(ap_socache_instance_t *context, server_rec *s)
167174 /* noop. */
168175}
169176
170- static void mc_session_id2sz (ap_socache_instance_t * ctx ,
177+ /* Converts (binary) id into a key prefixed by the predetermined
178+ * namespace tag; writes output to key buffer. Returns non-zero if
179+ * the id won't fit in the key buffer. */
180+ static int socache_mc_id2key (ap_socache_instance_t * ctx ,
171181 const unsigned char * id , unsigned int idlen ,
172- char * buf , apr_size_t buflen )
182+ char * key , apr_size_t keylen )
173183{
174- apr_size_t maxlen = (buflen - ctx -> taglen ) / 2 ;
175184 char * cp ;
176185 unsigned int n ;
177186
178- cp = apr_cpystrn (buf , ctx -> tag , ctx -> taglen );
179- for (n = 0 ; n < idlen && n < maxlen ; n ++ ) {
187+ if (idlen * 2 + ctx -> taglen >= keylen )
188+ return 1 ;
189+
190+ cp = apr_cpystrn (key , ctx -> tag , ctx -> taglen );
191+
192+ for (n = 0 ; n < idlen ; n ++ ) {
180193 apr_snprintf (cp , 3 , "%02X" , (unsigned ) id [n ]);
181194 cp += 2 ;
182195 }
183196
184197 * cp = '\0' ;
198+ return 0 ;
185199}
186200
187201static apr_status_t socache_mc_store (ap_socache_instance_t * ctx , server_rec * s ,
@@ -192,7 +206,9 @@ static apr_status_t socache_mc_store(ap_socache_instance_t *ctx, server_rec *s,
192206 char buf [MC_KEY_LEN ];
193207 apr_status_t rv ;
194208
195- mc_session_id2sz (ctx , id , idlen , buf , sizeof (buf ));
209+ if (socache_mc_id2key (ctx , id , idlen , buf , sizeof buf )) {
210+ return APR_EINVAL ;
211+ }
196212
197213 rv = apr_memcache_set (ctx -> mc , buf , (char * )ucaData , nData , timeout , 0 );
198214
@@ -216,7 +232,9 @@ static apr_status_t socache_mc_retrieve(ap_socache_instance_t *ctx,
216232 char buf [MC_KEY_LEN ], * der ;
217233 apr_status_t rv ;
218234
219- mc_session_id2sz (ctx , id , idlen , buf , sizeof (buf ));
235+ if (socache_mc_id2key (ctx , id , idlen , buf , sizeof buf )) {
236+ return APR_EINVAL ;
237+ }
220238
221239 /* ### this could do with a subpool, but _getp looks like it will
222240 * eat memory like it's going out of fashion anyway. */
@@ -249,7 +267,9 @@ static void socache_mc_remove(ap_socache_instance_t *ctx, server_rec *s,
249267 char buf [MC_KEY_LEN ];
250268 apr_status_t rv ;
251269
252- mc_session_id2sz (ctx , id , idlen , buf , sizeof (buf ));
270+ if (socache_mc_id2key (ctx , id , idlen , buf , sizeof buf )) {
271+ return ;
272+ }
253273
254274 rv = apr_memcache_delete (ctx -> mc , buf , 0 );
255275
0 commit comments