aboutsummaryrefslogtreecommitdiffstats
path: root/g10/build-packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/build-packet.c')
-rw-r--r--g10/build-packet.c96
1 files changed, 90 insertions, 6 deletions
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 0f297b0e7..c4fcb1345 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -648,13 +648,83 @@ find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
return NULL;
}
+/****************
+ * Delete all subpackets of type REQTYPE and return the number of bytes
+ * which are now unused at the end of the buffer.
+ */
+size_t
+delete_sig_subpkt( byte *buffer, sigsubpkttype_t reqtype )
+{
+ int buflen, orig_buflen;
+ sigsubpkttype_t type;
+ byte *bufstart, *orig_buffer;
+ size_t n;
+ size_t unused = 0;
+ int okay = 0;
+
+ if( !buffer )
+ return 0;
+ orig_buffer = buffer;
+ buflen = (*buffer << 8) | buffer[1];
+ buffer += 2;
+ orig_buflen = buflen;
+ for(;;) {
+ if( !buflen ) {
+ okay = 1;
+ break;
+ }
+ bufstart = buffer;
+ n = *buffer++; buflen--;
+ if( n == 255 ) {
+ if( buflen < 4 )
+ break;
+ n = (buffer[0] << 24) | (buffer[1] << 16)
+ | (buffer[2] << 8) | buffer[3];
+ buffer += 4;
+ buflen -= 4;
+ }
+ else if( n >= 192 ) {
+ if( buflen < 2 )
+ break;
+ n = (( n - 192 ) << 8) + *buffer + 192;
+ buffer++;
+ buflen--;
+ }
+ if( buflen < n )
+ break;
+ type = *buffer & 0x7f;
+ if( type == reqtype ) {
+ buffer++;
+ buflen--;
+ n--;
+ if( n > buflen )
+ break;
+ memmove (bufstart, buffer + n, n + (buffer-bufstart)); /* shift */
+ unused += n + (buffer-bufstart);
+ buffer = bufstart;
+ buflen -= n;
+ }
+ else {
+ buffer += n; buflen -=n;
+ }
+ }
+
+ if (!okay)
+ log_error("delete_subpkt: buffer shorter than subpacket\n");
+ assert (unused <= orig_buflen);
+ orig_buflen -= unused;
+ orig_buffer[0] = (orig_buflen >> 8) & 0xff;
+ orig_buffer[1] = orig_buflen & 0xff;
+ return unused;
+}
+
/****************
* Create or update a signature subpacket for SIG of TYPE.
* This functions knows where to put the data (hashed or unhashed).
- * The function may move data from the unhased part to the hashed one.
+ * The function may move data from the unhashed part to the hashed one.
* Note: All pointers into sig->[un]hashed are not valid after a call
- * to this function. The data to but into the subpaket should be
+ * to this function. The data to put into the subpaket should be
* in buffer with a length of buflen.
*/
void
@@ -666,6 +736,7 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
int found=0;
int critical, hashed, realloced;
size_t n, n0;
+ size_t unused = 0;
critical = (type & SIGSUBPKT_FLAG_CRITICAL);
type &= ~SIGSUBPKT_FLAG_CRITICAL;
@@ -677,6 +748,12 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
else if( (data = find_subpkt( sig->unhashed_data, type, &hlen, &dlen )))
found = 2;
+ if (found==2 && type == SIGSUBPKT_PRIV_VERIFY_CACHE) {
+ unused = delete_sig_subpkt (sig->unhashed_data, type);
+ assert (unused);
+ found = 0;
+ }
+
if( found )
log_bug("build_sig_packet: update nyi\n");
if( (buflen+1) >= 8384 )
@@ -688,7 +765,6 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
- case SIGSUBPKT_PRIV_ADD_SIG:
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
@@ -713,9 +789,17 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
n0 = sig->unhashed_data ? ((*sig->unhashed_data << 8)
| sig->unhashed_data[1]) : 0;
n = n0 + nlen + 1 + buflen; /* length, type, buffer */
- realloced = !!sig->unhashed_data;
- data = sig->unhashed_data ? m_realloc( sig->unhashed_data, n+2 )
- : m_alloc( n+2 );
+ if ( sig->unhashed_data && (nlen + 1 + buflen) <= unused ) {
+ /* does fit into the freed area */
+ data = sig->unhashed_data;
+ realloced = 1;
+ log_debug ("updating area of type %d\n", type );
+ }
+ else {
+ realloced = !!sig->unhashed_data;
+ data = sig->unhashed_data ? m_realloc( sig->unhashed_data, n+2 )
+ : m_alloc( n+2 );
+ }
}
if( critical )