Skip to content

Commit 1dcfb8d

Browse files
committed
Refactor space allocation for base64 encoding/decoding in pgcrypto.
Instead of trying to accurately calculate the space needed, use a StringInfo that's enlarged as needed. This is just moving things around currently - the old code was not wrong - but this is in preparation for a patch that adds support for extra armor headers, and would make the space calculation more complicated. Marko Tiikkaja
1 parent 56a312a commit 1dcfb8d

File tree

3 files changed

+59
-73
lines changed

3 files changed

+59
-73
lines changed

contrib/pgcrypto/pgp-armor.c

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -203,38 +203,33 @@ crc24(const uint8 *data, unsigned len)
203203
return crc & 0xffffffL;
204204
}
205205

206-
int
207-
pgp_armor_encode(const uint8 *src, unsigned len, uint8 *dst)
206+
void
207+
pgp_armor_encode(const uint8 *src, int len, StringInfo dst)
208208
{
209-
int n;
210-
uint8 *pos = dst;
209+
int res;
210+
unsigned b64len;
211211
unsigned crc = crc24(src, len);
212212

213-
n = strlen(armor_header);
214-
memcpy(pos, armor_header, n);
215-
pos += n;
216-
217-
n = b64_encode(src, len, pos);
218-
pos += n;
213+
appendStringInfoString(dst, armor_header);
219214

220-
if (*(pos - 1) != '\n')
221-
*pos++ = '\n';
215+
/* make sure we have enough room to b64_encode() */
216+
b64len = b64_enc_len(len);
217+
enlargeStringInfo(dst, (int) b64len);
218+
res = b64_encode(src, len, (uint8 *) dst->data + dst->len);
219+
if (res > b64len)
220+
elog(FATAL, "overflow - encode estimate too small");
221+
dst->len += res;
222222

223-
*pos++ = '=';
224-
pos[3] = _base64[crc & 0x3f];
225-
crc >>= 6;
226-
pos[2] = _base64[crc & 0x3f];
227-
crc >>= 6;
228-
pos[1] = _base64[crc & 0x3f];
229-
crc >>= 6;
230-
pos[0] = _base64[crc & 0x3f];
231-
pos += 4;
223+
if (*(dst->data + dst->len - 1) != '\n')
224+
appendStringInfoChar(dst, '\n');
232225

233-
n = strlen(armor_footer);
234-
memcpy(pos, armor_footer, n);
235-
pos += n;
226+
appendStringInfoChar(dst, '=');
227+
appendStringInfoChar(dst, _base64[(crc >> 18) & 0x3f]);
228+
appendStringInfoChar(dst, _base64[(crc >> 12) & 0x3f]);
229+
appendStringInfoChar(dst, _base64[(crc >> 6) & 0x3f]);
230+
appendStringInfoChar(dst, _base64[crc & 0x3f]);
236231

237-
return pos - dst;
232+
appendStringInfoString(dst, armor_footer);
238233
}
239234

240235
static const uint8 *
@@ -309,7 +304,7 @@ find_header(const uint8 *data, const uint8 *datend,
309304
}
310305

311306
int
312-
pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst)
307+
pgp_armor_decode(const uint8 *src, int len, StringInfo dst)
313308
{
314309
const uint8 *p = src;
315310
const uint8 *data_end = src + len;
@@ -319,6 +314,7 @@ pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst)
319314
const uint8 *base64_end = NULL;
320315
uint8 buf[4];
321316
int hlen;
317+
int blen;
322318
int res = PXE_PGP_CORRUPT_ARMOR;
323319

324320
/* armor start */
@@ -360,23 +356,18 @@ pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst)
360356
crc = (((long) buf[0]) << 16) + (((long) buf[1]) << 8) + (long) buf[2];
361357

362358
/* decode data */
363-
res = b64_decode(base64_start, base64_end - base64_start, dst);
364-
365-
/* check crc */
366-
if (res >= 0 && crc24(dst, res) != crc)
367-
res = PXE_PGP_CORRUPT_ARMOR;
359+
blen = (int) b64_dec_len(len);
360+
enlargeStringInfo(dst, blen);
361+
res = b64_decode(base64_start, base64_end - base64_start, (uint8 *) dst->data);
362+
if (res > blen)
363+
elog(FATAL, "overflow - decode estimate too small");
364+
if (res >= 0)
365+
{
366+
if (crc24((uint8 *) dst->data, res) == crc)
367+
dst->len += res;
368+
else
369+
res = PXE_PGP_CORRUPT_ARMOR;
370+
}
368371
out:
369372
return res;
370373
}
371-
372-
unsigned
373-
pgp_armor_enc_len(unsigned len)
374-
{
375-
return b64_enc_len(len) + strlen(armor_header) + strlen(armor_footer) + 16;
376-
}
377-
378-
unsigned
379-
pgp_armor_dec_len(unsigned len)
380-
{
381-
return b64_dec_len(len);
382-
}

contrib/pgcrypto/pgp-pgsql.c

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "postgres.h"
3333

34+
#include "lib/stringinfo.h"
3435
#include "mb/pg_wchar.h"
3536
#include "utils/builtins.h"
3637

@@ -820,23 +821,20 @@ pg_armor(PG_FUNCTION_ARGS)
820821
{
821822
bytea *data;
822823
text *res;
823-
int data_len,
824-
res_len,
825-
guess_len;
824+
int data_len;
825+
StringInfoData buf;
826826

827827
data = PG_GETARG_BYTEA_P(0);
828828
data_len = VARSIZE(data) - VARHDRSZ;
829829

830-
guess_len = pgp_armor_enc_len(data_len);
831-
res = palloc(VARHDRSZ + guess_len);
830+
initStringInfo(&buf);
832831

833-
res_len = pgp_armor_encode((uint8 *) VARDATA(data), data_len,
834-
(uint8 *) VARDATA(res));
835-
if (res_len > guess_len)
836-
ereport(ERROR,
837-
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
838-
errmsg("Overflow - encode estimate too small")));
839-
SET_VARSIZE(res, VARHDRSZ + res_len);
832+
pgp_armor_encode((uint8 *) VARDATA(data), data_len, &buf);
833+
834+
res = palloc(VARHDRSZ + buf.len);
835+
SET_VARSIZE(res, VARHDRSZ + buf.len);
836+
memcpy(VARDATA(res), buf.data, buf.len);
837+
pfree(buf.data);
840838

841839
PG_FREE_IF_COPY(data, 0);
842840
PG_RETURN_TEXT_P(res);
@@ -847,27 +845,24 @@ pg_dearmor(PG_FUNCTION_ARGS)
847845
{
848846
text *data;
849847
bytea *res;
850-
int data_len,
851-
res_len,
852-
guess_len;
848+
int data_len;
849+
int ret;
850+
StringInfoData buf;
853851

854852
data = PG_GETARG_TEXT_P(0);
855853
data_len = VARSIZE(data) - VARHDRSZ;
856854

857-
guess_len = pgp_armor_dec_len(data_len);
858-
res = palloc(VARHDRSZ + guess_len);
855+
initStringInfo(&buf);
859856

860-
res_len = pgp_armor_decode((uint8 *) VARDATA(data), data_len,
861-
(uint8 *) VARDATA(res));
862-
if (res_len < 0)
857+
ret = pgp_armor_decode((uint8 *) VARDATA(data), data_len, &buf);
858+
if (ret < 0)
863859
ereport(ERROR,
864860
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
865-
errmsg("%s", px_strerror(res_len))));
866-
if (res_len > guess_len)
867-
ereport(ERROR,
868-
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
869-
errmsg("Overflow - decode estimate too small")));
870-
SET_VARSIZE(res, VARHDRSZ + res_len);
861+
errmsg("%s", px_strerror(ret))));
862+
res = palloc(VARHDRSZ + buf.len);
863+
SET_VARSIZE(res, VARHDRSZ + buf.len);
864+
memcpy(VARDATA(res), buf.data, buf.len);
865+
pfree(buf.data);
871866

872867
PG_FREE_IF_COPY(data, 0);
873868
PG_RETURN_TEXT_P(res);

contrib/pgcrypto/pgp.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
* contrib/pgcrypto/pgp.h
3030
*/
3131

32+
#include "lib/stringinfo.h"
33+
3234
#include "mbuf.h"
3335
#include "px.h"
3436

@@ -274,10 +276,8 @@ void pgp_cfb_free(PGP_CFB *ctx);
274276
int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
275277
int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
276278

277-
int pgp_armor_encode(const uint8 *src, unsigned len, uint8 *dst);
278-
int pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst);
279-
unsigned pgp_armor_enc_len(unsigned len);
280-
unsigned pgp_armor_dec_len(unsigned len);
279+
void pgp_armor_encode(const uint8 *src, int len, StringInfo dst);
280+
int pgp_armor_decode(const uint8 *src, int len, StringInfo dst);
281281

282282
int pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst);
283283
int pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy