Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package usbredir for openSUSE:Factory 
checked in at 2021-12-22 20:17:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/usbredir (Old)
 and      /work/SRC/openSUSE:Factory/.usbredir.new.2520 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "usbredir"

Wed Dec 22 20:17:47 2021 rev:16 rq:941785 version:0.12.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/usbredir/usbredir.changes        2021-08-26 
23:14:38.232258872 +0200
+++ /work/SRC/openSUSE:Factory/.usbredir.new.2520/usbredir.changes      
2021-12-22 20:18:23.967856411 +0100
@@ -1,0 +2,12 @@
+Mon Dec 20 23:10:25 UTC 2021 - Dirk M??ller <dmuel...@suse.com>
+
+- update to 0.12.0:
+  * Implement dropping packets from isochronous devices
+    when buffer is owned by usbredirparser library
+  * Use packet size limit on deserialization
+  * Fix possible bad state in deserialization logic
+  * Fix possible memory leak in serialization logic
+  * Fix (un)serialization with empty write buffers
+  * Improvements to usbredirparserfuzz
+
+-------------------------------------------------------------------

Old:
----
  usbredir-0.11.0.tar.xz
  usbredir-0.11.0.tar.xz.sig

New:
----
  usbredir-0.12.0.tar.xz
  usbredir-0.12.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ usbredir.spec ++++++
--- /var/tmp/diff_new_pack.XTD9Mv/_old  2021-12-22 20:18:24.519856670 +0100
+++ /var/tmp/diff_new_pack.XTD9Mv/_new  2021-12-22 20:18:24.527856673 +0100
@@ -18,7 +18,7 @@
 
 
 Name:           usbredir
-Version:        0.11.0
+Version:        0.12.0
 Release:        0
 Summary:        A protocol for redirecting USB traffic
 License:        GPL-2.0-or-later AND LGPL-2.1-or-later

++++++ usbredir-0.11.0.tar.xz -> usbredir-0.12.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/ChangeLog.md 
new/usbredir-0.12.0/ChangeLog.md
--- old/usbredir-0.11.0/ChangeLog.md    2021-08-10 08:13:51.746648000 +0200
+++ new/usbredir-0.12.0/ChangeLog.md    2021-11-12 11:45:49.992210900 +0100
@@ -1,3 +1,13 @@
+# usbredir-0.12.0 - 12 Nov 2021
+
+- !47 Implement dropping packets from isochronous devices
+  when buffer is owned by usbredirparser library
+- !50 Use packet size limit on deserialization
+- !54 Fix possible bad state in deserialization logic
+- !48 Fix possible memory leak in serialization logic
+- !45 Fix (un)serialization with empty write buffers
+- !42 !46 !52 Improvements to usbredirparserfuzz
+
 # usbredir-0.11.0 - 10 Aug 2021
 
 - !40 Fixes use-after-free on usbredirparser serialization
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/build-aux/oss-fuzz.sh 
new/usbredir-0.12.0/build-aux/oss-fuzz.sh
--- old/usbredir-0.11.0/build-aux/oss-fuzz.sh   2021-08-10 08:13:51.746648000 
+0200
+++ new/usbredir-0.12.0/build-aux/oss-fuzz.sh   2021-11-12 11:45:49.994210700 
+0100
@@ -46,6 +46,9 @@
 
     # Don't use "-Wl,--no-undefined"
     -Db_lundef=false
+
+    # Enable internal tests
+    -Dextra-checks=true
     )
 
 if ! meson setup "${config[@]}" -- "$builddir"; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/fuzzing/usbredirparserfuzz.cc 
new/usbredir-0.12.0/fuzzing/usbredirparserfuzz.cc
--- old/usbredir-0.11.0/fuzzing/usbredirparserfuzz.cc   2021-08-10 
08:13:51.747648000 +0200
+++ new/usbredir-0.12.0/fuzzing/usbredirparserfuzz.cc   2021-11-12 
11:45:50.003210800 +0100
@@ -19,9 +19,10 @@
 #include <array>
 #include <algorithm>
 #include <memory>
+#include <type_traits>
 
+#include <cassert>
 #include <cinttypes>
-#include <cstdio>
 #include <cstring>
 #include <limits>
 
@@ -43,37 +44,49 @@
 std::unique_ptr<struct usbredirparser, ParserDeleter> parser;
 std::unique_ptr<FuzzedDataProvider> fdp;
 
-void log(const char *format, ...)
+void parser_log(void *priv, int level, const char *msg)
 {
-#if 0
-    va_list args;
-
-    va_start(args, format);
-    vfprintf(stderr, format, args);
-    va_end(args);
-#endif
 }
 
-void parser_log(void *priv, int level, const char *msg)
+int wobbly_read_write_count(int count)
 {
-    log("[%d] %s\n", level, msg);
+    if (count > (1024 * 1024)) {
+        return count;
+    }
+
+    return std::min(count, fdp->ConsumeIntegralInRange(1, 4 * count));
 }
 
 int parser_read(void *priv, uint8_t *data, int count)
 {
-    log("%s: %d bytes\n", __func__, count);
+    // Simulate short reads
+    return fdp->ConsumeData(data, wobbly_read_write_count(count));
+}
 
-    return fdp->ConsumeData(data, count);
+// Read over complete input buffer to detect buffer overflows
+void read_all(const void *data, size_t count)
+{
+#ifdef __cpp_lib_smart_ptr_for_overwrite
+    const auto buf = std::make_unique_for_overwrite<uint8_t[]>(count);
+#else
+    const auto buf = std::make_unique<uint8_t[]>(count);
+#endif
+
+    memcpy(buf.get(), data, count);
+}
+
+template <typename T, typename = std::enable_if_t<std::is_class<T>::value>>
+void read_all(const T *ptr)
+{
+    read_all(ptr, sizeof(T));
 }
 
 int parser_write(void *priv, uint8_t *data, int count)
 {
-    log("%s: %d bytes\n", __func__, count);
+    // Simulate short writes
+    count = wobbly_read_write_count(count);
 
-    // Read over complete source buffer to detect buffer overflows on write
-    void *buf = malloc(count);
-    memcpy(buf, data, count);
-    free(buf);
+    read_all(data, count);
 
     return count;
 }
@@ -81,60 +94,24 @@
 void parser_device_connect(void *priv,
     struct usb_redir_device_connect_header *device_connect)
 {
-    log("%s: speed=%d, class=%d, subclass=%d, protocol=%d, vendor=%04x,"
-        " product=%04x\n",
-        __func__,
-        device_connect->speed,
-        device_connect->device_class,
-        device_connect->device_subclass,
-        device_connect->device_protocol,
-        device_connect->vendor_id,
-        device_connect->product_id);
 }
 
 void parser_device_disconnect(void *priv)
 {
-    log("%s\n", __func__);
 }
 
 void parser_reset(void *priv)
 {
-    log("%s\n", __func__);
 }
 
 void parser_interface_info(void *priv,
     struct usb_redir_interface_info_header *info)
 {
-    uint32_t i;
-
-    log("%s:", __func__);
-
-    for (i = 0; i < info->interface_count; i++) {
-        log(" [interface %d, class %d, subclass %d, protocol %d]",
-            info->interface[i], info->interface_class[i],
-            info->interface_subclass[i], info->interface_protocol[i]);
-    }
-
-    log("\n");
 }
 
 void parser_ep_info(void *priv,
     struct usb_redir_ep_info_header *ep_info)
 {
-    int i;
-
-    log("%s:", __func__);
-
-    for (i = 0; i < 32; i++) {
-        if (ep_info->type[i] != usb_redir_type_invalid) {
-            log(" [index %d, type %d, interval %d, interface %d,"
-                " max-packetsize %d]",
-                i, (int)ep_info->type[i], (int)ep_info->interval[i],
-                (int)ep_info->interface[i], ep_info->max_packet_size[i]);
-       }
-    }
-
-    log("\n");
 }
 
 void parser_set_configuration(void *priv, uint64_t id,
@@ -149,8 +126,6 @@
 void parser_configuration_status(void *priv, uint64_t id,
     struct usb_redir_configuration_status_header *config_status)
 {
-    log("%s: id=%" PRIu64 ", status=%d, configuration=%d\n",
-        __func__, id, config_status->status, config_status->configuration);
 }
 
 void parser_set_alt_setting(void *priv, uint64_t id,
@@ -166,11 +141,6 @@
 void parser_alt_setting_status(void *priv, uint64_t id,
     struct usb_redir_alt_setting_status_header *alt_setting_status)
 {
-    log("%s: id=%" PRIu64 ", status=%d, interface=%d, alt=%d\n",
-        __func__, id,
-        alt_setting_status->status,
-        alt_setting_status->interface,
-        alt_setting_status->alt);
 }
 
 void parser_start_iso_stream(void *priv, uint64_t id,
@@ -232,36 +202,12 @@
     usbredirfilter_free(rules);
 }
 
-void dump_data(const uint8_t *data, const int len)
-{
-    int i;
-
-    if (len == 0) {
-        return;
-    }
-
-    log("  ");
-    for (i = 0; i < len; i++) {
-        log(" %02X", (unsigned int)data[i]);
-    }
-    log("\n");
-}
-
 void parser_control_packet(void *priv, uint64_t id,
     struct usb_redir_control_packet_header *control_packet,
     uint8_t *data, int data_len)
 {
-    log("%s: id=%" PRIu64 ", endpoint=%d, request=%d, requesttype=%d,"
-        " status=%d, value=%d, index=%d, length=%d\n",
-        __func__, id,
-        control_packet->endpoint,
-        control_packet->request,
-        control_packet->requesttype,
-        control_packet->status,
-        control_packet->value,
-        control_packet->index,
-        control_packet->length);
-    dump_data(data, data_len);
+    read_all(control_packet);
+    read_all(data, data_len);
     usbredirparser_free_packet_data(parser.get(), data);
 }
 
@@ -269,15 +215,8 @@
     struct usb_redir_bulk_packet_header *bulk_packet,
     uint8_t *data, int data_len)
 {
-    log("%s: id=%" PRIu64 ", endpoint=%d, status=%d, length=%d, stream_id=%d,"
-        " length_high=%d\n",
-        __func__, id,
-        bulk_packet->endpoint,
-        bulk_packet->status,
-        bulk_packet->length,
-        bulk_packet->stream_id,
-        bulk_packet->length_high);
-    dump_data(data, data_len);
+    read_all(bulk_packet);
+    read_all(data, data_len);
     usbredirparser_free_packet_data(parser.get(), data);
 }
 
@@ -285,12 +224,8 @@
     struct usb_redir_iso_packet_header *iso_packet,
     uint8_t *data, int data_len)
 {
-    log("%s: id=%" PRIu64 ", endpoint=%d, status=%d, length=%d\n",
-        __func__, id,
-        iso_packet->endpoint,
-        iso_packet->status,
-        iso_packet->length);
-    dump_data(data, data_len);
+    read_all(iso_packet);
+    read_all(data, data_len);
     usbredirparser_free_packet_data(parser.get(), data);
 }
 
@@ -298,12 +233,8 @@
     struct usb_redir_interrupt_packet_header *interrupt_packet,
     uint8_t *data, int data_len)
 {
-    log("%s: id=%" PRIu64 ", endpoint=%d, status=%d, length=%d\n",
-        __func__, id,
-        interrupt_packet->endpoint,
-        interrupt_packet->status,
-        interrupt_packet->length);
-    dump_data(data, data_len);
+    read_all(interrupt_packet);
+    read_all(data, data_len);
     usbredirparser_free_packet_data(parser.get(), data);
 }
 
@@ -311,13 +242,8 @@
     struct usb_redir_buffered_bulk_packet_header *buffered_bulk_header,
     uint8_t *data, int data_len)
 {
-    log("%s: stream_id=%d, length=%d, endpoint=%d, status=%d\n",
-        __func__, id,
-        buffered_bulk_header->stream_id,
-        buffered_bulk_header->length,
-        buffered_bulk_header->endpoint,
-        buffered_bulk_header->status);
-    dump_data(data, data_len);
+    read_all(buffered_bulk_header);
+    read_all(data, data_len);
     usbredirparser_free_packet_data(parser.get(), data);
 }
 
@@ -340,7 +266,6 @@
 
 void parser_hello(void *priv, struct usb_redir_hello_header *h)
 {
-    log("%s: %s\n", __func__, h->version);
 }
 
 void parser_device_disconnect_ack(void *priv)
@@ -350,16 +275,19 @@
 void parser_start_bulk_receiving(void *priv, uint64_t id,
     struct usb_redir_start_bulk_receiving_header *start_bulk_receiving)
 {
+    read_all(start_bulk_receiving);
 }
 
 void parser_stop_bulk_receiving(void *priv, uint64_t id,
     struct usb_redir_stop_bulk_receiving_header *stop_bulk_receiving)
 {
+    read_all(stop_bulk_receiving);
 }
 
 void parser_bulk_receiving_status(void *priv, uint64_t id,
     struct usb_redir_bulk_receiving_status_header *bulk_receiving_status)
 {
+    read_all(bulk_receiving_status);
 }
 
 int try_unserialize(struct usbredirparser *parser, FuzzedDataProvider *fdp)
@@ -370,9 +298,11 @@
     state.reserve(len);
 
     if (len >= 4) {
-        // Could also move USBREDIRPARSER_SERIALIZE_MAGIC after moving it to
-        // a shared header.
-        state.insert(state.end(), {'U', 'R', 'P', '1'});
+        const uint32_t magic = USBREDIRPARSER_SERIALIZE_MAGIC;
+        assert(state.empty());
+        state.resize(sizeof(magic));
+        memcpy(state.data(), &magic, sizeof(magic));
+
         len -= 4;
     }
 
@@ -488,7 +418,6 @@
                 // Keep reading
                 break;
             default:
-                log("usbredirparser_do_read failed: %d\n", ret);
                 goto out;
             }
 
@@ -500,7 +429,6 @@
         while (usbredirparser_has_data_to_write(parser.get())) {
             ret = usbredirparser_do_write(parser.get());
             if (ret < 0) {
-                log("usbredirparser_do_write failed: %d\n", ret);
                 goto out;
             }
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/meson.build 
new/usbredir-0.12.0/meson.build
--- old/usbredir-0.11.0/meson.build     2021-08-10 08:13:51.747648000 +0200
+++ new/usbredir-0.12.0/meson.build     2021-11-12 11:45:50.003210800 +0100
@@ -1,5 +1,5 @@
-project('usbredir', 'c', 'cpp',
-    version: '0.11.0',
+project('usbredir', 'c',
+    version: '0.12.0',
     license: 'LGPLv2.1+',
     meson_version : '>= 0.53',
     default_options : [
@@ -15,10 +15,10 @@
     '--param=ssp-buffer-size=4',
 ]
 if host_machine.system() != 'windows'
-    cc_flags += [
-       '-Wp,-D_FORTIFY_SOURCE=2',
-       '-fstack-protector',
-    ]
+    cc_flags += [ '-Wp,-D_FORTIFY_SOURCE=2' ]
+    if not get_option('stack_protector').disabled()
+        cc_flags += [ '-fstack-protector' ]
+    endif
 endif
 
 # Check if we are building from .git
@@ -34,6 +34,10 @@
 
 config = configuration_data()
 
+if get_option('extra-checks')
+  config.set('ENABLE_EXTRA_CHECKS', '1')
+endif
+
 config.set('USBREDIR_VISIBLE', '')
 foreach visibility : [
     '__attribute__((visibility ("default")))',
@@ -106,7 +110,9 @@
         subdir('fuzzing')
     endif
 endif
-subdir('tests')
+if get_option('tests').enabled()
+    subdir('tests')
+endif
 subdir('data')
 
 summary(summary_info, bool_yn: true)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/meson_options.txt 
new/usbredir-0.12.0/meson_options.txt
--- old/usbredir-0.11.0/meson_options.txt       2021-08-10 08:13:51.747648000 
+0200
+++ new/usbredir-0.12.0/meson_options.txt       2021-11-12 11:45:50.003210800 
+0100
@@ -17,7 +17,22 @@
     type : 'string',
     description : 'Installation directory for fuzzing binaries')
 
+option('stack_protector',
+    type : 'feature',
+    value : 'enabled',
+    description : 'Build usbredir\'s with stack-protector')
+
 option('tools',
     type : 'feature',
     value : 'enabled',
     description : 'Build usbredir\'s tools such as usbredirect')
+
+option('tests',
+    type : 'feature',
+    value : 'enabled',
+    description : 'Build usbredir\'s tests such as filter')
+
+option('extra-checks',
+    type : 'boolean',
+    value : false,
+    description : 'Enable extra checks on code. Do not use for production')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/tools/usbredirect.c 
new/usbredir-0.12.0/tools/usbredirect.c
--- old/usbredir-0.11.0/tools/usbredirect.c     2021-08-10 08:13:51.747648000 
+0200
+++ new/usbredir-0.12.0/tools/usbredirect.c     2021-11-12 11:45:50.009210800 
+0100
@@ -519,7 +519,7 @@
             self,
             PACKAGE_STRING,
             self->verbosity,
-            usbredirhost_fl_write_cb_owns_buffer);
+            0);
     if (!self->usbredirhost) {
         g_warning("Error starting usbredirhost");
         goto err_init;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirhost/meson.build 
new/usbredir-0.12.0/usbredirhost/meson.build
--- old/usbredir-0.11.0/usbredirhost/meson.build        2021-08-10 
08:13:51.747648000 +0200
+++ new/usbredir-0.12.0/usbredirhost/meson.build        2021-11-12 
11:45:50.009210800 +0100
@@ -1,7 +1,7 @@
 # so verison, see:
 # 
http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
 usbredir_host_current = 1
-usbredir_host_revision = 2
+usbredir_host_revision = 3
 usbredir_host_age = 0
 usbredir_host_so_version = '@0@.@1@.@2@'.format(
     usbredir_host_current - usbredir_host_age,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirhost/usbredirhost.c 
new/usbredir-0.12.0/usbredirhost/usbredirhost.c
--- old/usbredir-0.11.0/usbredirhost/usbredirhost.c     2021-08-10 
08:13:51.748648200 +0200
+++ new/usbredir-0.12.0/usbredirhost/usbredirhost.c     2021-11-12 
11:45:50.011210700 +0100
@@ -116,6 +116,7 @@
     usbredirhost_buffered_output_size buffered_output_size_func;
     void *func_priv;
     int verbose;
+    int flags;
     libusb_context *ctx;
     libusb_device *dev;
     libusb_device_handle *handle;
@@ -691,6 +692,7 @@
     host->func_priv = func_priv;
     host->verbose = verbose;
     host->disconnected = 1; /* No device is connected initially */
+    host->flags = flags;
     host->parser = usbredirparser_create();
     if (!host->parser) {
         log_func(func_priv, usbredirparser_error,
@@ -1042,10 +1044,17 @@
 {
     uint64_t size;
 
-    if (!host->buffered_output_size_func)
-        return true;
+    if (host->flags & usbredirhost_fl_write_cb_owns_buffer) {
+        if (!host->buffered_output_size_func) {
+            /* Application is not dropping isoc packages */
+            return true;
+        }
+        size = host->buffered_output_size_func(host->func_priv);
+    } else {
+        /* queue is on usbredirparser */
+        size = usbredirparser_get_bufferered_output_size(host->parser);
+    }
 
-    size = host->buffered_output_size_func(host->func_priv);
     if (size >= host->iso_threshold.higher) {
         if (!host->iso_threshold.dropping)
             DEBUG("START dropping isoc packets %" PRIu64 " buffer > %" PRIu64 
" hi threshold",
@@ -1442,6 +1451,13 @@
         return;
     }
 
+    if (!(host->flags & usbredirhost_fl_write_cb_owns_buffer)) {
+        host->log_func(host->func_priv, usbredirparser_warning,
+                       "can't set callback as usbredirhost owns the output "
+                       "buffer (flag: usbredirhost_fl_write_cb_owns_buffer)");
+        return;
+    }
+
     host->buffered_output_size_func = buffered_output_size_func;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirhost/usbredirhost.h 
new/usbredir-0.12.0/usbredirhost/usbredirhost.h
--- old/usbredir-0.11.0/usbredirhost/usbredirhost.h     2021-08-10 
08:13:51.748648200 +0200
+++ new/usbredir-0.12.0/usbredirhost/usbredirhost.h     2021-11-12 
11:45:50.012210800 +0100
@@ -18,8 +18,7 @@
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
-#ifndef __USBREDIRHOST_H
-#define __USBREDIRHOST_H
+#pragma once
 
 #include <libusb.h>
 #include "usbredirparser.h"
@@ -182,5 +181,3 @@
 #ifdef __cplusplus
 }
 #endif
-
-#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirparser/meson.build 
new/usbredir-0.12.0/usbredirparser/meson.build
--- old/usbredir-0.11.0/usbredirparser/meson.build      2021-08-10 
08:13:51.748648200 +0200
+++ new/usbredir-0.12.0/usbredirparser/meson.build      2021-11-12 
11:45:50.013210800 +0100
@@ -1,8 +1,8 @@
 # so verison, see:
 # 
http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
-usbredir_parser_current = 2
+usbredir_parser_current = 3
 usbredir_parser_revision = 0
-usbredir_parser_age = 1
+usbredir_parser_age = 2
 usbredir_parser_so_version = '@0@.@1@.@2@'.format(
     usbredir_parser_current - usbredir_parser_age,
     usbredir_parser_age,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirparser/strtok_r.h 
new/usbredir-0.12.0/usbredirparser/strtok_r.h
--- old/usbredir-0.11.0/usbredirparser/strtok_r.h       2021-08-10 
08:13:51.748648200 +0200
+++ new/usbredir-0.12.0/usbredirparser/strtok_r.h       2021-11-12 
11:45:50.013210800 +0100
@@ -16,11 +16,7 @@
    License along with the GNU C Library; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
-
-#ifndef _USBREDIRPARSER_STRTOK_H_
-#define _USBREDIRPARSER_STRTOK_H_
+#pragma once
 
 char *
 glibc_strtok_r(char *s, const char *delim, char **save_ptr);
-
-#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirparser/usbredirfilter.h 
new/usbredir-0.12.0/usbredirparser/usbredirfilter.h
--- old/usbredir-0.11.0/usbredirparser/usbredirfilter.h 2021-08-10 
08:13:51.748648200 +0200
+++ new/usbredir-0.12.0/usbredirparser/usbredirfilter.h 2021-11-12 
11:45:50.015210900 +0100
@@ -18,8 +18,7 @@
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
-#ifndef __USBREDIRFILTER_H
-#define __USBREDIRFILTER_H
+#pragma once
 
 #include <stdio.h>
 #include <stdint.h>
@@ -139,5 +138,3 @@
 #ifdef __cplusplus
 }
 #endif
-
-#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirparser/usbredirparser.c 
new/usbredir-0.12.0/usbredirparser/usbredirparser.c
--- old/usbredir-0.11.0/usbredirparser/usbredirparser.c 2021-08-10 
08:13:51.748648200 +0200
+++ new/usbredir-0.12.0/usbredirparser/usbredirparser.c 2021-11-12 
11:45:50.017210700 +0100
@@ -20,6 +20,7 @@
 */
 #include "config.h"
 
+#include <assert.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -81,8 +82,9 @@
     int data_len;
     int data_read;
     int to_skip;
-    struct usbredirparser_buf *write_buf;
     int write_buf_count;
+    struct usbredirparser_buf *write_buf;
+    uint64_t write_buf_total_size;
 };
 
 static void
@@ -110,6 +112,38 @@
 #define INFO(...)    va_log(parser, usbredirparser_info, __VA_ARGS__)
 #define DEBUG(...)    va_log(parser, usbredirparser_debug, __VA_ARGS__)
 
+static inline void
+usbredirparser_assert_invariants(const struct usbredirparser_priv *parser)
+{
+#ifdef ENABLE_EXTRA_CHECKS
+    assert(parser != NULL);
+    assert(parser->header_read >= 0);
+    assert(parser->header_read <= sizeof(parser->header));
+    assert(parser->type_header_read >= 0);
+    assert(parser->type_header_len <= sizeof(parser->type_header));
+    assert(parser->type_header_read <= parser->type_header_len);
+    assert(parser->data_len >= 0);
+    assert(parser->data_len <= MAX_PACKET_SIZE);
+    assert(parser->data_read >= 0);
+    assert(parser->data_read <= parser->data_len);
+    assert((parser->data_len != 0) ^ (parser->data == NULL));
+
+    int write_buf_count = 0;
+    uint64_t total_size = 0;
+    const struct usbredirparser_buf *write_buf = parser->write_buf;
+    for (; write_buf != NULL ; write_buf = write_buf->next) {
+        assert(write_buf->pos >= 0);
+        assert(write_buf->len >= 0);
+        assert(write_buf->pos <= write_buf->len);
+        assert(write_buf->len == 0 || write_buf->buf != NULL);
+        write_buf_count++;
+        total_size += write_buf->len;
+    }
+    assert(parser->write_buf_count == write_buf_count);
+    assert(parser->write_buf_total_size == total_size);
+#endif
+}
+
 #if 0 /* Can be enabled and called from random place to test serialization */
 static void serialize_test(struct usbredirparser *parser_pub)
 {
@@ -219,6 +253,19 @@
     free(parser);
 }
 
+USBREDIR_VISIBLE
+uint64_t usbredirparser_get_bufferered_output_size(struct usbredirparser 
*parser_pub)
+{
+    struct usbredirparser_priv *parser =
+        (struct usbredirparser_priv *)parser_pub;
+    uint64_t size;
+
+    LOCK(parser);
+    size = parser->write_buf_total_size;
+    UNLOCK(parser);
+    return size;
+}
+
 static int usbredirparser_caps_get_cap(struct usbredirparser_priv *parser,
     uint32_t *caps, int cap)
 {
@@ -973,13 +1020,16 @@
 
     header_len = usbredirparser_get_header_len(parser_pub);
 
+    usbredirparser_assert_invariants(parser);
     /* Skip forward to next packet (only used in error conditions) */
     while (parser->to_skip > 0) {
         uint8_t buf[65536];
         r = (parser->to_skip > sizeof(buf)) ? sizeof(buf) : parser->to_skip;
         r = parser->callb.read_func(parser->callb.priv, buf, r);
-        if (r <= 0)
+        if (r <= 0) {
+            usbredirparser_assert_invariants(parser);
             return r;
+        }
         parser->to_skip -= r;
     }
 
@@ -999,6 +1049,7 @@
         if (r > 0) {
             r = parser->callb.read_func(parser->callb.priv, dest, r);
             if (r <= 0) {
+                usbredirparser_assert_invariants(parser);
                 return r;
             }
         }
@@ -1014,6 +1065,7 @@
                           parser->header.type);
                     parser->to_skip = parser->header.length;
                     parser->header_read = 0;
+                    usbredirparser_assert_invariants(parser);
                     return usbredirparser_read_parse_error;
                 }
                 /* This should never happen */
@@ -1021,6 +1073,7 @@
                     ERROR("error type specific header buffer too small, please 
report!!");
                     parser->to_skip = parser->header.length;
                     parser->header_read = 0;
+                    usbredirparser_assert_invariants(parser);
                     return usbredirparser_read_parse_error;
                 }
                 if (parser->header.length > MAX_PACKET_SIZE) {
@@ -1028,6 +1081,7 @@
                           parser->header.length, MAX_PACKET_SIZE);
                     parser->to_skip = parser->header.length;
                     parser->header_read = 0;
+                    usbredirparser_assert_invariants(parser);
                     return usbredirparser_read_parse_error;
                 }
                 if ((int)parser->header.length < type_header_len ||
@@ -1037,6 +1091,7 @@
                           parser->header.type, parser->header.length);
                     parser->to_skip = parser->header.length;
                     parser->header_read = 0;
+                    usbredirparser_assert_invariants(parser);
                     return usbredirparser_read_parse_error;
                 }
                 data_len = parser->header.length - type_header_len;
@@ -1046,6 +1101,7 @@
                         ERROR("Out of memory allocating data buffer");
                         parser->to_skip = parser->header.length;
                         parser->header_read = 0;
+                        usbredirparser_assert_invariants(parser);
                         return usbredirparser_read_parse_error;
                     }
                 }
@@ -1074,8 +1130,10 @@
                 parser->data_len  = 0;
                 parser->data_read = 0;
                 parser->data = NULL;
-                if (!r)
+                if (!r) {
+                    usbredirparser_assert_invariants(parser);
                     return usbredirparser_read_parse_error;
+                }
                 /* header len may change if this was an hello packet */
                 header_len = usbredirparser_get_header_len(parser_pub);
             }
@@ -1100,6 +1158,8 @@
     int w, ret = 0;
 
     LOCK(parser);
+    assert((parser->write_buf_count != 0) ^ (parser->write_buf == NULL));
+
     for (;;) {
         wbuf = parser->write_buf;
         if (!wbuf)
@@ -1123,8 +1183,10 @@
             parser->write_buf = wbuf->next;
             if (!(parser->flags & usbredirparser_fl_write_cb_owns_buffer))
                 free(wbuf->buf);
-            free(wbuf);
+
+            parser->write_buf_total_size -= wbuf->len;
             parser->write_buf_count--;
+            free(wbuf);
         }
     }
     UNLOCK(parser);
@@ -1154,7 +1216,7 @@
     uint8_t *buf, *type_header_out, *data_out;
     struct usb_redir_header *header;
     struct usbredirparser_buf *wbuf, *new_wbuf;
-    int header_len, type_header_len;
+    int header_len, type_header_len, total_size;
 
     header_len = usbredirparser_get_header_len(parser_pub);
     type_header_len = usbredirparser_get_type_header_len(parser_pub, type, 1);
@@ -1169,8 +1231,9 @@
         return;
     }
 
+    total_size = header_len + type_header_len + data_len;
     new_wbuf = calloc(1, sizeof(*new_wbuf));
-    buf = malloc(header_len + type_header_len + data_len);
+    buf = malloc(total_size);
     if (!new_wbuf || !buf) {
         ERROR("Out of memory allocating buffer to send packet, dropping!");
         free(new_wbuf); free(buf);
@@ -1178,7 +1241,7 @@
     }
 
     new_wbuf->buf = buf;
-    new_wbuf->len = header_len + type_header_len + data_len;
+    new_wbuf->len = total_size;
 
     header = (struct usb_redir_header *)buf;
     type_header_out = buf + header_len;
@@ -1204,6 +1267,7 @@
 
         wbuf->next = new_wbuf;
     }
+    parser->write_buf_total_size += total_size;
     parser->write_buf_count++;
     UNLOCK(parser);
 }
@@ -1496,7 +1560,6 @@
 
 /****** Serialization support ******/
 
-#define USBREDIRPARSER_SERIALIZE_MAGIC        0x55525031
 #define USBREDIRPARSER_SERIALIZE_BUF_SIZE     65536
 
 /* Serialization format, send and receiving endian are expected to be the same!
@@ -1742,25 +1805,43 @@
     uint8_t *data;
     uint32_t i, l, header_len, remain = len;
 
-    if (unserialize_int(parser, &state, &remain, &i, "magic"))
+    usbredirparser_assert_invariants(parser);
+    if (unserialize_int(parser, &state, &remain, &i, "magic")) {
+        usbredirparser_assert_invariants(parser);
         return -1;
+    }
     if (i != USBREDIRPARSER_SERIALIZE_MAGIC) {
         ERROR("error unserialize magic mismatch");
+        usbredirparser_assert_invariants(parser);
         return -1;
     }
 
-    if (unserialize_int(parser, &state, &remain, &i, "length"))
+    if (!(parser->write_buf_count == 0 && parser->write_buf == NULL &&
+          parser->write_buf_total_size == 0 &&
+          parser->data == NULL && parser->header_read == 0 &&
+          parser->type_header_read == 0 && parser->data_read == 0)) {
+        ERROR("unserialization must use a pristine parser");
+        usbredirparser_assert_invariants(parser);
         return -1;
+    }
+
+    if (unserialize_int(parser, &state, &remain, &i, "length")) {
+        usbredirparser_assert_invariants(parser);
+        return -1;
+    }
     if (i != len) {
         ERROR("error unserialize length mismatch");
+        usbredirparser_assert_invariants(parser);
         return -1;
     }
 
     data = (uint8_t *)parser->our_caps;
     i = USB_REDIR_CAPS_SIZE * sizeof(int32_t);
     memcpy(orig_caps, parser->our_caps, i);
-    if (unserialize_data(parser, &state, &remain, &data, &i, "our_caps"))
+    if (unserialize_data(parser, &state, &remain, &data, &i, "our_caps")) {
+        usbredirparser_assert_invariants(parser);
         return -1;
+    }
     for (i =0; i < USB_REDIR_CAPS_SIZE; i++) {
         if (parser->our_caps[i] != orig_caps[i]) {
             /* orig_caps is our original settings
@@ -1772,6 +1853,7 @@
                 /* Source has a cap we don't */
                 ERROR("error unserialize caps mismatch ours: %x recv: %x",
                       orig_caps[i], parser->our_caps[i]);
+                usbredirparser_assert_invariants(parser);
                 return -1;
             } else {
                 /* We've got a cap the source doesn't - that's OK */
@@ -1783,80 +1865,136 @@
 
     data = (uint8_t *)parser->peer_caps;
     i = USB_REDIR_CAPS_SIZE * sizeof(int32_t);
-    if (unserialize_data(parser, &state, &remain, &data, &i, "peer_caps"))
+    if (unserialize_data(parser, &state, &remain, &data, &i, "peer_caps")) {
+        usbredirparser_assert_invariants(parser);
         return -1;
+    }
     if (i)
         parser->have_peer_caps = 1;
 
-    if (unserialize_int(parser, &state, &remain, &i, "skip"))
+    if (unserialize_int(parser, &state, &remain, &i, "skip")) {
+        usbredirparser_assert_invariants(parser);
         return -1;
+    }
     parser->to_skip = i;
 
     header_len = usbredirparser_get_header_len(parser_pub);
     data = (uint8_t *)&parser->header;
     i = header_len;
-    if (unserialize_data(parser, &state, &remain, &data, &i, "header"))
+    if (unserialize_data(parser, &state, &remain, &data, &i, "header")) {
+        usbredirparser_assert_invariants(parser);
         return -1;
+    }
     parser->header_read = i;
+    parser->type_header_len = 0;
 
-    /* Set various length field froms the header (if we've a header) */
+    /* Set various length field from the header (if any) */
     if (parser->header_read == header_len) {
-                int type_header_len =
-                    usbredirparser_get_type_header_len(parser_pub,
-                                                       parser->header.type, 0);
-                if (type_header_len < 0 ||
-                    type_header_len > sizeof(parser->type_header) ||
-                    parser->header.length < type_header_len ||
-                    (parser->header.length > type_header_len &&
-                     !usbredirparser_expect_extra_data(parser))) {
-                    ERROR("error unserialize packet header invalid");
-                    return -1;
-                }
-                parser->type_header_len = type_header_len;
-                parser->data_len = parser->header.length - type_header_len;
+        if (parser->header.length > MAX_PACKET_SIZE) {
+            ERROR("packet length of %d larger than permitted %d bytes",
+                  parser->header.length, MAX_PACKET_SIZE);
+            return -1;
+        }
+
+        int type_header_len =
+            usbredirparser_get_type_header_len(parser_pub,
+                                               parser->header.type, 0);
+        if (type_header_len < 0 ||
+            type_header_len > sizeof(parser->type_header) ||
+            parser->header.length < type_header_len ||
+            (parser->header.length > type_header_len &&
+             !usbredirparser_expect_extra_data(parser))) {
+            ERROR("error unserialize packet header invalid");
+            usbredirparser_assert_invariants(parser);
+            return -1;
+        }
+        parser->type_header_len = type_header_len;
     }
 
     data = parser->type_header;
     i = parser->type_header_len;
-    if (unserialize_data(parser, &state, &remain, &data, &i, "type_header"))
+    if (unserialize_data(parser, &state, &remain, &data, &i, "type_header")) {
+        usbredirparser_assert_invariants(parser);
         return -1;
-    parser->type_header_read = i;
+    }
+    if (parser->header_read == header_len) {
+        parser->type_header_read = i;
+    }
 
-    if (parser->data_len) {
-        parser->data = malloc(parser->data_len);
-        if (!parser->data) {
-            ERROR("Out of memory allocating unserialize buffer");
-            return -1;
+    if (parser->type_header_read == parser->type_header_len) {
+        parser->data_len = parser->header.length - parser->type_header_len;
+        if (parser->data_len) {
+            parser->data = malloc(parser->data_len);
+            if (!parser->data) {
+                ERROR("Out of memory allocating unserialize buffer");
+                usbredirparser_assert_invariants(parser);
+                return -1;
+            }
         }
     }
     i = parser->data_len;
-    if (unserialize_data(parser, &state, &remain, &parser->data, &i, "data"))
+    if (unserialize_data(parser, &state, &remain, &parser->data, &i, "data")) {
+        free(parser->data);
+        parser->data = NULL;
+        parser->data_len = 0;
+        usbredirparser_assert_invariants(parser);
         return -1;
-    parser->data_read = i;
+    }
+    if (parser->header_read == header_len &&
+        parser->type_header_read == parser->type_header_len &&
+        parser->data_len > 0) {
+        parser->data_read = i;
+    } else if (parser->data != NULL) {
+        free(parser->data);
+        parser->data = NULL;
+        parser->data_len = 0;
+    }
 
     /* Get the write buffer count and the write buffers */
-    if (unserialize_int(parser, &state, &remain, &i, "write_buf_count"))
+    if (unserialize_int(parser, &state, &remain, &i, "write_buf_count")) {
+        usbredirparser_assert_invariants(parser);
         return -1;
+    }
     next = &parser->write_buf;
+    usbredirparser_assert_invariants(parser);
     while (i) {
+        uint8_t *buf = NULL;
+
+        l = 0;
+        if (unserialize_data(parser, &state, &remain, &buf, &l, "wbuf")) {
+            usbredirparser_assert_invariants(parser);
+            return -1;
+        }
+
+        if (l == 0) {
+            free(buf);
+            ERROR("write buffer %d is empty", i);
+            usbredirparser_assert_invariants(parser);
+            return -1;
+        }
+
         wbuf = calloc(1, sizeof(*wbuf));
         if (!wbuf) {
+            free(buf);
             ERROR("Out of memory allocating unserialize buffer");
+            usbredirparser_assert_invariants(parser);
             return -1;
         }
-        *next = wbuf;
-        l = 0;
-        if (unserialize_data(parser, &state, &remain, &wbuf->buf, &l, "wbuf"))
-            return -1;
+        wbuf->buf = buf;
         wbuf->len = l;
+        *next = wbuf;
         next = &wbuf->next;
+        parser->write_buf_total_size += wbuf->len;
+        parser->write_buf_count++;
         i--;
     }
 
     if (remain) {
         ERROR("error unserialize %d bytes of extraneous state data", remain);
+        usbredirparser_assert_invariants(parser);
         return -1;
     }
 
+    usbredirparser_assert_invariants(parser);
     return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirparser/usbredirparser.h 
new/usbredir-0.12.0/usbredirparser/usbredirparser.h
--- old/usbredir-0.11.0/usbredirparser/usbredirparser.h 2021-08-10 
08:13:51.749648000 +0200
+++ new/usbredir-0.12.0/usbredirparser/usbredirparser.h 2021-11-12 
11:45:50.018210600 +0100
@@ -18,11 +18,12 @@
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
-#ifndef __USBREDIRPARSER_H
-#define __USBREDIRPARSER_H
+#pragma once
 
 #include "usbredirproto.h"
 
+#define USBREDIRPARSER_SERIALIZE_MAGIC 0x55525031
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -244,6 +245,11 @@
 /* This returns the number of usbredir packets queued up for writing */
 int usbredirparser_has_data_to_write(struct usbredirparser *parser);
 
+/* This returns the number of bytes queued to be written out. Can be used by 
control plane
+ * to drop data from being queued, see issue:
+ * https://gitlab.freedesktop.org/spice/usbredir/-/issues/19 */ 
+uint64_t usbredirparser_get_bufferered_output_size(struct usbredirparser 
*parser_pub);
+
 /* Call this when usbredirparser_has_data_to_write returns > 0
    returns 0 on success, -1 if a write error happened.
    If a write error happened, this function will retry writing any queued data
@@ -382,5 +388,3 @@
 #ifdef __cplusplus
 }
 #endif
-
-#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirparser/usbredirparser.map 
new/usbredir-0.12.0/usbredirparser/usbredirparser.map
--- old/usbredir-0.11.0/usbredirparser/usbredirparser.map       2021-08-10 
08:13:51.749648000 +0200
+++ new/usbredir-0.12.0/usbredirparser/usbredirparser.map       2021-11-12 
11:45:50.019210800 +0100
@@ -59,4 +59,10 @@
     usbredirfilter_free;
 } USBREDIRPARSER_0.8.0;
 
+USBREDIRPARSER_0.11.0 {
+global:
+    usbredirparser_get_bufferered_output_size;
+} USBREDIRPARSER_0.10.0;
+
+
 # .... define new API here using predicted next version number ....
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/usbredir-0.11.0/usbredirparser/usbredirproto-compat.h 
new/usbredir-0.12.0/usbredirparser/usbredirproto-compat.h
--- old/usbredir-0.11.0/usbredirparser/usbredirproto-compat.h   2021-08-10 
08:13:51.749648000 +0200
+++ new/usbredir-0.12.0/usbredirparser/usbredirproto-compat.h   2021-11-12 
11:45:50.019210800 +0100
@@ -18,8 +18,7 @@
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
-#ifndef __USBREDIRPROTO_COMPAT_H
-#define __USBREDIRPROTO_COMPAT_H
+#pragma once
 
 /* PACK macros borrowed from spice-protocol */
 #ifdef __GNUC__
@@ -82,5 +81,3 @@
 #if defined(__MINGW32__) || !defined(__GNUC__)
 #pragma pack(pop)
 #endif
-
-#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/usbredir-0.11.0/usbredirparser/usbredirproto.h 
new/usbredir-0.12.0/usbredirparser/usbredirproto.h
--- old/usbredir-0.11.0/usbredirparser/usbredirproto.h  2021-08-10 
08:13:51.749648000 +0200
+++ new/usbredir-0.12.0/usbredirparser/usbredirproto.h  2021-11-12 
11:45:50.020210700 +0100
@@ -18,8 +18,7 @@
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
-#ifndef __USBREDIRPROTO_H
-#define __USBREDIRPROTO_H
+#pragma once
 
 /* PACK macros borrowed from spice-protocol */
 #ifdef __GNUC__
@@ -303,5 +302,3 @@
 #ifdef __cplusplus
 }
 #endif
-
-#endif

Reply via email to