@@ -503,13 +503,35 @@ struct bufRead: public libzpaq::Reader {
503503struct bufWrite : public libzpaq ::Writer {
504504 uchar *c_buf;
505505 i64 *c_len;
506- bufWrite (uchar *buf_, i64 *n_): c_buf(buf_), c_len(n_) {}
506+ i64 max_len;
507+ bufWrite (uchar *buf_, i64 *n_, i64 max_ = -1LL ): c_buf(buf_), c_len(n_), max_len(max_) {}
507508
508509 void put (int c) {
509- c_buf[(*c_len)++] = (uchar)c;
510+ // c_buf[(*c_len)++] = (uchar)c;
511+ if (*c_len < 0 ) return ;
512+ if (max_len >= 0 && *c_len >= max_len) {
513+ *c_len = -1 ;
514+ return ;
515+ }
516+ c_buf[(*c_len)++] = static_cast <uchar>(c);
510517 }
511518
512519 void write (const char *buf, int n) {
520+ if (n <= 0 || *c_len < 0 ) return ;
521+ if (max_len < 0 ) {
522+ memcpy (c_buf + *c_len, buf, n);
523+ *c_len += n;
524+ return ;
525+ }
526+ i64 avail = max_len - *c_len;
527+ if (avail <= 0 ) {
528+ *c_len = -1 ;
529+ return ;
530+ }
531+ if ((i64 )n > avail) {
532+ *c_len = -1 ;
533+ return ;
534+ }
513535 memcpy (c_buf + *c_len, buf, n);
514536 *c_len += n;
515537 }
@@ -527,16 +549,19 @@ extern "C" void zpaq_compress(uchar *c_buf, i64 *c_len, uchar *s_buf, i64 s_len,
527549 compress (&bufR, &bufW, level);
528550}
529551
530- extern " C" void zpaq_decompress (uchar *s_buf, i64 *d_len, uchar *c_buf, i64 c_len,
531- FILE *msgout, bool progress, long thread)
552+ extern " C" int zpaq_decompress (uchar *s_buf, i64 *d_len, uchar *c_buf, i64 c_len,
553+ FILE *msgout, bool progress, long thread,
554+ i64 expected_len)
532555{
533556 i64 total_len = c_len;
534557 int last_pct = 100 ;
535558
536559 bufRead bufR (c_buf, &c_len, total_len, &last_pct, progress, thread, msgout);
537- bufWrite bufW (s_buf, d_len);
560+ bufWrite bufW (s_buf, d_len, expected_len );
538561
539562 decompress (&bufR, &bufW);
563+ if (*d_len < 0 ) return -1 ; // overflow attempt detected
564+ return 0 ;
540565}
541566
542567#endif // LIBZPAQ_H
0 commit comments