@@ -27,7 +27,7 @@
 #include "spline.h"
 #include "color.h"
 #include "output-dxf.h"
-#include "xstd.h"
+#include <glib.h>
 #include "autotrace.h"
 #include <math.h>
 #include <time.h>
@@ -387,7 +387,7 @@ void xypnt_add_pnt(xypnt_head_rec * head_xypnt /*  */ ,

   if (!head_xypnt)
     return;
-  temp_point = (struct xypnt_point_t *)calloc(1, sizeof(struct xypnt_point_t));
+  temp_point = g_malloc0(sizeof(struct xypnt_point_t));
   temp_point->point = coord_point;
   temp_point->next_point = NULL;
   if (head_xypnt->first_point == NULL)
@@ -410,7 +410,7 @@ void xypnt_dispose_list(xypnt_head_rec ** head_xypnt /*  */ )
       while (p) {
         old = p;
         p = p->next_point;
-        free(old);
+        g_free(old);
       }
     }
   }
@@ -518,11 +518,11 @@ int bspline_to_lines(xypnt_head_rec * vtx_list /*  */ ,
   xypnt curr_pnt, spline_pnt;
   char end_of_list;

-  *new_vtx_list = (struct xypnt_head_t *)calloc(1, sizeof(struct xypnt_head_t));
+  *new_vtx_list = g_malloc0(sizeof(struct xypnt_head_t));
   if (vtx_list) {
     n = vtx_count + spline_order + 1;
     m = spline_order + 1;
-    XMALLOC(weight, n * m * sizeof(double));
+    weight = g_malloc((gsize)n * m * sizeof(double));

     for (i = 0; i < vtx_count + spline_order; i++)
       knot[i] = (i < spline_order) ? 0 : (i > vtx_count) ? knot[i - 1] : knot[i - 1] + 1;
@@ -564,7 +564,7 @@ int bspline_to_lines(xypnt_head_rec * vtx_list /*  */ ,
     xypnt_last_pnt(vtx_list, &spline_pnt, &end_of_list);
     xypnt_add_pnt(*new_vtx_list, spline_pnt);

-    free(weight);
+    g_free(weight);
   }

   return (0);
@@ -636,7 +636,7 @@ static void out_splines(FILE * dxf_file, spline_list_array_type shape)
         pnt_old.xp = lround(startx * RESOLUTION);
         pnt_old.yp = lround(starty * RESOLUTION);
       } else {
-        vec = (struct xypnt_head_t *)calloc(1, sizeof(struct xypnt_head_t));
+        vec = g_malloc0(sizeof(struct xypnt_head_t));

         pnt.xp = lround(startx * RESOLUTION);
         pnt.yp = lround(starty * RESOLUTION);
@@ -682,8 +682,8 @@ static void out_splines(FILE * dxf_file, spline_list_array_type shape)
         startx = END_POINT(s).x;
         starty = END_POINT(s).y;

-        free(res);
-        free(vec);
+        g_free(res);
+        g_free(vec);
       }
     }
     first_seg = 0;


Merge pull request #110 from lemenkov/HKUST-CVEs

HKUST CVEs

@@ -25,7 +25,6 @@
 #include "output-pstoedit.h"
 #include "output-p2e.h"
 #include "filename.h"
-#include "xstd.h"

 #include <pstoedit/pstoedit.h>
 #include <stdio.h>


binutils: Use file descriptors from make_tempname

The purpose of creating a temporary file securely using mkstemp is
defeated if it is closed in make_tempname and reopened later for use;
it is as good as using mktemp.  Get the file descriptor instead and
then use it to create the BFD object.

bfd/

	* opncls.c (bfd_fdopenw): New function.
	* bfd-in2.h: Regenerate.

binutils/

	* bucomm.c (make_tempname): Add argument to return file
	descriptor.
	* bucomm.h (make_tempname): Likewise.
	* ar.c: Include libbfd.h.
	(write_archive): Adjust for change in make_tempname.  Call
	bfd_fdopenw instead of bfd_openw.
	* objcopy.c: Include libbfd.h.
	(copy_file): New argument OFD.  Use bfd_fdopenw instead of
	bfd_openw.
	(strip_main): Adjust for change in make_tempname and
	copy_file.
	(copy_main): Likewise.

@@ -393,6 +393,39 @@ bfd_fdopenr (const char *filename, const char *target, int fd)
   return bfd_fopen (filename, target, mode, fd);
 }

+/*
+FUNCTION
+	bfd_fdopenw
+
+SYNOPSIS
+	bfd *bfd_fdopenw (const char *filename, const char *target, int fd);
+
+DESCRIPTION
+	<<bfd_fdopenw>> is exactly like <<bfd_fdopenr>> with the exception that
+	the resulting BFD is suitable for output.
+*/
+
+bfd *
+bfd_fdopenw (const char *filename, const char *target, int fd)
+{
+  bfd *out = bfd_fdopenr (filename, target, fd);
+
+  if (out != NULL)
+    {
+      if (!bfd_write_p (out))
+	{
+	  close (fd);
+	  _bfd_delete_bfd (out);
+	  out = NULL;
+	  bfd_set_error (bfd_error_invalid_operation);
+	}
+      else
+	out->direction = write_direction;
+    }
+
+  return out;
+}
+
 /*
 FUNCTION
 	bfd_openstreamr


Issue 4609 - CVE - info disclosure when authenticating

Description:  If you bind as a user that does not exist.  Error 49 is returned
              instead of error 32.  As error 32 discloses that the entry does
              not exist.  When you bind as an entry that does not have userpassword
              set then error 48 (inappropriate auth) is returned, but this
              discloses that the entry does indeed exist.  Instead we should
              always return error 49, even if the password is not set in the
              entry.  This way we do not disclose to an attacker if the Bind
              DN exists or not.

Relates: https://github.com/389ds/389-ds-base/issues/4609

Reviewed by: tbordaz(Thanks!)

@@ -1446,22 +1446,25 @@ dse_bind(Slapi_PBlock *pb) /* JCM There should only be one exit point from this

     ec = dse_get_entry_copy(pdse, sdn, DSE_USE_LOCK);
     if (ec == NULL) {
-        slapi_send_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL);
+        slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not exist");
+        slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
         return (SLAPI_BIND_FAIL);
     }

     switch (method) {
     case LDAP_AUTH_SIMPLE: {
         Slapi_Value cv;
         if (slapi_entry_attr_find(ec, "userpassword", &attr) != 0) {
-            slapi_send_ldap_result(pb, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, 0, NULL);
+            slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Entry does not have userpassword set");
+            slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
             slapi_entry_free(ec);
             return SLAPI_BIND_FAIL;
         }
         bvals = attr_get_present_values(attr);

         slapi_value_init_berval(&cv, cred);
         if (slapi_pw_find_sv(bvals, &cv) != 0) {
+            slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, "Invalid credentials");
             slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL);
             slapi_entry_free(ec);
             value_done(&cv);


sungem: switch to use qemu_receive_packet() for loopback

This patch switches to use qemu_receive_packet() which can detect
reentrancy and return early.

This is intended to address CVE-2021-3416.

Cc: Prasad J Pandit <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>

@@ -306,7 +306,7 @@ static void sungem_send_packet(SunGEMState *s, const uint8_t *buf,
     NetClientState *nc = qemu_get_queue(s->nic);

     if (s->macregs[MAC_XIFCFG >> 2] & MAC_XIFCFG_LBCK) {
-        nc->info->receive(nc, buf, size);
+        qemu_receive_packet(nc, buf, size);
     } else {
         qemu_send_packet(nc, buf, size);
     }


net: introduce qemu_receive_packet()

Some NIC supports loopback mode and this is done by calling
nc->info->receive() directly which in fact suppresses the effort of
reentrancy check that is done in qemu_net_queue_send().

Unfortunately we can't use qemu_net_queue_send() here since for
loopback there's no sender as peer, so this patch introduce a
qemu_receive_packet() which is used for implementing loopback mode
for a NIC with this check.

NIC that supports loopback mode will be converted to this helper.

This is intended to address CVE-2021-3416.

Cc: Prasad J Pandit <ppandit@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Jason Wang <jasowang@redhat.com>

@@ -182,6 +182,28 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
     return ret;
 }

+ssize_t qemu_net_queue_receive(NetQueue *queue,
+                               const uint8_t *data,
+                               size_t size)
+{
+    if (queue->delivering) {
+        return 0;
+    }
+
+    return qemu_net_queue_deliver(queue, NULL, 0, data, size);
+}
+
+ssize_t qemu_net_queue_receive_iov(NetQueue *queue,
+                                   const struct iovec *iov,
+                                   int iovcnt)
+{
+    if (queue->delivering) {
+        return 0;
+    }
+
+    return qemu_net_queue_deliver_iov(queue, NULL, 0, iov, iovcnt);
+}
+
 ssize_t qemu_net_queue_send(NetQueue *queue,
                             NetClientState *sender,
                             unsigned flags,


server: Wait until handshake complete before calling .open callback

Currently we call the plugin .open callback as soon as we receive a
TCP connection:

  $ nbdkit -fv --tls=require --tls-certificates=tests/pki null \
           --run "telnet localhost 10809"
  [...]
  Trying ::1...
  Connected to localhost.
  Escape character is '^]'.
  nbdkit: debug: accepted connection
  nbdkit: debug: null: open readonly=0       ◀ NOTE
  nbdkit: null[1]: debug: newstyle negotiation: flags: global 0x3
  NBDMAGICIHAVEOPT

In plugins such as curl, guestfs, ssh, vddk and others we do a
considerable amount of work in the .open callback (such as making a
remote connection or launching an appliance).  Therefore we are
providing an easy Denial of Service / Amplification Attack for
unauthorized clients to cause a lot of work to be done for only the
cost of a simple TCP 3 way handshake.

This commit moves the call to the .open callback after the NBD
handshake has mostly completed.  In particular TLS authentication must
be complete before we will call into the plugin.

It is unlikely that there are plugins which really depend on the
current behaviour of .open (which I found surprising even though I
guess I must have written it).  If there are then we could add a new
.connect callback or similar to allow plugins to get control at the
earlier point in the connection.

After this change you can see that the .open callback is not called
from just a simple TCP connection:

  $ ./nbdkit -fv --tls=require --tls-certificates=tests/pki null \
             --run "telnet localhost 10809"
  [...]
  Trying ::1...
  Connected to localhost.
  Escape character is '^]'.
  nbdkit: debug: accepted connection
  nbdkit: null[1]: debug: newstyle negotiation: flags: global 0x3
  NBDMAGICIHAVEOPT
  xx
  nbdkit: null[1]: debug: newstyle negotiation: client flags: 0xd0a7878
  nbdkit: null[1]: error: client requested unknown flags 0xd0a7878
  Connection closed by foreign host.
  nbdkit: debug: null: unload plugin

Signed-off-by: Richard W.M. Jones <rjones@redhat.com>

@@ -204,8 +204,9 @@ extern int connection_set_status (struct connection *conn, int value)
 /* protocol-handshake.c */
 extern int protocol_handshake (struct connection *conn)
   __attribute__((__nonnull__ (1)));
-extern int protocol_compute_eflags (struct connection *conn, uint16_t *flags)
-  __attribute__((__nonnull__ (1, 2)));
+extern int protocol_common_open (struct connection *conn,
+                                 uint64_t *exportsize, uint16_t *flags)
+  __attribute__((__nonnull__ (1, 2, 3)));

 /* protocol-handshake-oldstyle.c */
 extern int protocol_handshake_oldstyle (struct connection *conn)


lldp: avoid memory leak from bad packets

A packet that contains multiple instances of certain TLVs will cause
lldpd to continually allocate memory and leak the old memory.  As an
example, multiple instances of system name TLV will cause old values
to be dropped by the decoding routine.

Reported-at: https://github.com/openvswitch/ovs/pull/337
Reported-by: Jonas Rudloff <jonas.t.rudloff@gmail.com>
Signed-off-by: Aaron Conole <aconole@redhat.com>

@@ -816,11 +816,16 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
 				goto malformed;
 			}
 			PEEK_BYTES(b, tlv_size);
-			if (tlv_type == LLDP_TLV_PORT_DESCR)
+			if (tlv_type == LLDP_TLV_PORT_DESCR) {
+				free(port->p_descr);
 				port->p_descr = b;
-			else if (tlv_type == LLDP_TLV_SYSTEM_NAME)
+			} else if (tlv_type == LLDP_TLV_SYSTEM_NAME) {
+				free(chassis->c_name);
 				chassis->c_name = b;
-			else chassis->c_descr = b;
+			} else {
+				free(chassis->c_descr);
+				chassis->c_descr = b;
+			}
 			break;
 		case LLDP_TLV_SYSTEM_CAP:
 			CHECK_TLV_SIZE(4, "System capabilities");


dir: Reserve the whole @@ prefix

If we add new features analogous to file forwarding later, we might
find that we need a different magic token. Let's reserve the whole
@@* namespace so we can call it @@something-else.

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 1e7e8fdb24b51078f4c48e0711e24a14930ba1f0)

@@ -7139,7 +7139,7 @@ export_desktop_file (const char         *app,
                 g_string_append_printf (new_exec, " @@ %s @@", arg);
               else if (strcasecmp (arg, "%u") == 0)
                 g_string_append_printf (new_exec, " @@u %s @@", arg);
-              else if (strcmp (arg, "@@") == 0 || strcmp (arg, "@@u") == 0)
+              else if (g_str_has_prefix (arg, "@@"))
                 g_print (_("Skipping invalid Exec argument %s\n"), arg);
               else
                 g_string_append_printf (new_exec, " %s", arg);


checkout: fix bug that makes checkout follow symlinks in leading path

Before checking out a file, we have to confirm that all of its leading
components are real existing directories. And to reduce the number of
lstat() calls in this process, we cache the last leading path known to
contain only directories. However, when a path collision occurs (e.g.
when checking out case-sensitive files in case-insensitive file
systems), a cached path might have its file type changed on disk,
leaving the cache on an invalid state. Normally, this doesn't bring
any bad consequences as we usually check out files in index order, and
therefore, by the time the cached path becomes outdated, we no longer
need it anyway (because all files in that directory would have already
been written).

But, there are some users of the checkout machinery that do not always
follow the index order. In particular: checkout-index writes the paths
in the same order that they appear on the CLI (or stdin); and the
delayed checkout feature -- used when a long-running filter process
replies with "status=delayed" -- postpones the checkout of some entries,
thus modifying the checkout order.

When we have to check out an out-of-order entry and the lstat() cache is
invalid (due to a previous path collision), checkout_entry() may end up
using the invalid data and thrusting that the leading components are
real directories when, in reality, they are not. In the best case
scenario, where the directory was replaced by a regular file, the user
will get an error: "fatal: unable to create file 'foo/bar': Not a
directory". But if the directory was replaced by a symlink, checkout
could actually end up following the symlink and writing the file at a
wrong place, even outside the repository. Since delayed checkout is
affected by this bug, it could be used by an attacker to write
arbitrary files during the clone of a maliciously crafted repository.

Some candidate solutions considered were to disable the lstat() cache
during unordered checkouts or sort the entries before passing them to
the checkout machinery. But both ideas include some performance penalty
and they don't future-proof the code against new unordered use cases.

Instead, we now manually reset the lstat cache whenever we successfully
remove a directory. Note: We are not even checking whether the directory
was the same as the lstat cache points to because we might face a
scenario where the paths refer to the same location but differ due to
case folding, precomposed UTF-8 issues, or the presence of `..`
components in the path. Two regression tests, with case-collisions and
utf8-collisions, are also added for both checkout-index and delayed
checkout.

Note: to make the previously mentioned clone attack unfeasible, it would
be sufficient to reset the lstat cache only after the remove_subtree()
call inside checkout_entry(). This is the place where we would remove a
directory whose path collides with the path of another entry that we are
currently trying to check out (possibly a symlink). However, in the
interest of a thorough fix that does not leave Git open to
similar-but-not-identical attack vectors, we decided to intercept
all `rmdir()` calls in one fell swoop.

This addresses CVE-2021-21300.

Co-authored-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>

@@ -267,6 +267,13 @@ int has_dirs_only_path(const char *name, int len, int prefix_len)
  */
 static int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len)
 {
+	/*
+	 * Note: this function is used by the checkout machinery, which also
+	 * takes care to properly reset the cache when it performs an operation
+	 * that would leave the cache outdated. If this function starts caching
+	 * anything else besides FL_DIR, remember to also invalidate the cache
+	 * when creating or deleting paths that might be in the cache.
+	 */
 	return lstat_cache(cache, name, len,
 			   FL_DIR|FL_FULLPATH, prefix_len) &
 		FL_DIR;
@@ -321,3 +328,20 @@ void remove_scheduled_dirs(void)
 {
 	do_remove_scheduled_dirs(0);
 }
+
+void invalidate_lstat_cache(void)
+{
+	reset_lstat_cache(&default_cache);
+}
+
+#undef rmdir
+int lstat_cache_aware_rmdir(const char *path)
+{
+	/* Any change in this function must be made also in `mingw_rmdir()` */
+	int ret = rmdir(path);
+
+	if (!ret)
+		invalidate_lstat_cache();
+
+	return ret;
+}


@@ -69,9 +69,9 @@ static inline int GetMagickNumberThreads(const Image *source,
        (GetImagePixelCacheType(source) != MapCache)) ||
       ((GetImagePixelCacheType(destination) != MemoryCache) &&
        (GetImagePixelCacheType(destination) != MapCache)))
-    return(MagickMax(MagickMin(GetMagickResourceLimit(ThreadResource),2),1));
-  return(MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),
-    (ssize_t) (chunk)/64),1));
+    return((int) MagickMax(MagickMin(GetMagickResourceLimit(ThreadResource),2),1));
+  return((int) MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(
+    ThreadResource),(ssize_t) (chunk)/64),1));
 }

 static inline size_t GetMagickThreadSignature(void)


drm/nouveau/svm: initial support for shared virtual memory

This uses HMM to mirror a process' CPU page tables into a channel's page
tables, and keep them synchronised so that both the CPU and GPU are able
to access the same memory at the same virtual address.

While this code also supports Volta/Turing, it's only enabled for Pascal
GPUs currently due to channel recovery being unreliable right now on the
later GPUs.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>

@@ -25,6 +25,7 @@ void nouveau_vma_unmap(struct nouveau_vma *);
 struct nouveau_vmm {
 	struct nouveau_cli *cli;
 	struct nvif_vmm vmm;
+	struct nouveau_svmm *svmm;
 };

 int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *);


Move auth_token_state from multi to key_state

The auth-token check is tied to the username/password that is coming
via a specific SSL session, so keep the state also in the key_state
structure.

This also ensures the auth_token_state is always set to 0 on a new
session since we clear the key_state object at the start of a new
SSL session.

This is a prerequisite patch to fix 2020-15078 in the following two
commits.

2nd patch, squashed into the first one:

This also applies the changes to the auth_token_test.c. The change of
tls_session to a pointer is necessary since before that we had tls_session
not tied to the multi and had two tls_session used in the test. One
implicitly in tls_multi and one explicit one. Merge these to one.

CVE: 2020-15078
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <d25ec73f-2ab0-31df-8cb6-7778000f4822@openvpn.net>
URL: non-public, embargoed
Signed-off-by: Gert Doering <gert@greenie.muc.de>

@@ -1269,7 +1269,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
      */
     if (session->opt->auth_token_generate && is_auth_token(up->password))
     {
-        multi->auth_token_state_flags = verify_auth_token(up, multi, session);
+        ks->auth_token_state_flags = verify_auth_token(up, multi, session);
         if (session->opt->auth_token_call_auth)
         {
             /*
@@ -1278,7 +1278,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
              * decide what to do with the result
              */
         }
-        else if (multi->auth_token_state_flags == AUTH_TOKEN_HMAC_OK)
+        else if (ks->auth_token_state_flags == AUTH_TOKEN_HMAC_OK)
         {
             /*
              * We do not want the EXPIRED or EMPTY USER flags here so check
@@ -1373,8 +1373,8 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi,
              * the initial timestamp and session id can be extracted from it
              */
             if (!multi->auth_token
-                && (multi->auth_token_state_flags & AUTH_TOKEN_HMAC_OK)
-                && !(multi->auth_token_state_flags & AUTH_TOKEN_EXPIRED))
+                && (ks->auth_token_state_flags & AUTH_TOKEN_HMAC_OK)
+                && !(ks->auth_token_state_flags & AUTH_TOKEN_EXPIRED))
             {
                 multi->auth_token = strdup(up->password);
             }


Improve heap2 bounds checking (#224)

* Improve heap bounds checking in pvPortMalloc

@@ -136,34 +136,42 @@ void * pvPortMalloc( size_t xWantedSize )
          * kernel, so it must be free. */
         if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
         {
-            /* The wanted size is increased so it can contain a BlockLink_t
+            /* The wanted size must be increased so it can contain a BlockLink_t
              * structure in addition to the requested amount of bytes. */
-            if( xWantedSize > 0 )
+            if( ( xWantedSize > 0 ) &&
+                ( ( xWantedSize + xHeapStructSize ) >  xWantedSize ) ) /* Overflow check */
             {
                 xWantedSize += xHeapStructSize;

-                /* Ensure that blocks are always aligned to the required number
-                 * of bytes. */
+                /* Ensure that blocks are always aligned. */
                 if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
                 {
-                    /* Byte alignment required. */
-                    xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
-                    configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
+                    /* Byte alignment required. Check for overflow. */
+                    if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) )
+                            > xWantedSize )
+                    {
+                        xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
+                        configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
+                    }
+                    else
+                    {
+                        xWantedSize = 0;
+                    }
                 }
                 else
                 {
                     mtCOVERAGE_TEST_MARKER();
                 }
-            }
-            else
+            }
+            else
             {
-                mtCOVERAGE_TEST_MARKER();
+                xWantedSize = 0;
             }

             if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
             {
                 /* Traverse the list from the start	(lowest address) block until
-                 * one	of adequate size is found. */
+                 * one of adequate size is found. */
                 pxPreviousBlock = &xStart;
                 pxBlock = xStart.pxNextFreeBlock;

@@ -174,7 +182,7 @@ void * pvPortMalloc( size_t xWantedSize )
                 }

                 /* If the end marker was reached then a block of adequate size
-                 * was	not found. */
+                 * was not found. */
                 if( pxBlock != pxEnd )
                 {
                     /* Return the memory space pointed to - jumping over the


@@ -102,6 +102,9 @@ void CleanWriters(GF_List *writers)
 {
 	while (gf_list_count(writers)) {
 		TrackWriter *writer = (TrackWriter*)gf_list_get(writers, 0);
+		//in case we have an error in the middle of file write, remove our created stco and stsc from sample table
+		gf_list_del_item(writer->stbl->child_boxes, writer->stco);
+		gf_list_del_item(writer->stbl->child_boxes, writer->stsc);
 		gf_isom_box_del(writer->stco);
 		gf_isom_box_del((GF_Box *)writer->stsc);
 		gf_free(writer);


add safety in avc/hevc/vvc sps/pps/vps ID check - cf #1720 #1721 #1722

@@ -5115,10 +5115,7 @@ static s32 gf_avc_read_sps_bs_internal(GF_BitStream *bs, AVCState *avc, u32 subs
 	by subset SPS. According to the SVC standard, subset SPS can have the same sps_id
 	than its base layer, but it does not refer to the same SPS. */
 	sps_id = gf_bs_read_ue_log(bs, "sps_id") + GF_SVC_SSPS_ID_SHIFT * subseq_sps;
-	if (sps_id >= 32) {
-		return -1;
-	}
-	if (sps_id < 0) {
+	if ((sps_id < 0) || (sps_id >= 32)) {
 		return -1;
 	}

@@ -5447,15 +5444,15 @@ static s32 gf_avc_read_pps_bs_internal(GF_BitStream *bs, AVCState *avc, u32 nal_
 		gf_bs_read_int_log(bs, 5, "nal_unit_type");
 	}
 	pps_id = gf_bs_read_ue_log(bs, "pps_id");
-	if (pps_id >= 255) {
+	if ((pps_id<0) || (pps_id >= 255)) {
 		return -1;
 	}
 	pps = &avc->pps[pps_id];
 	pps->id = pps_id;

 	if (!pps->status) pps->status = 1;
 	pps->sps_id = gf_bs_read_ue_log(bs, "sps_id");
-	if (pps->sps_id >= 32) {
+	if ((pps->sps_id<0) || (pps->sps_id >= 32)) {
 		pps->sps_id = 0;
 		return -1;
 	}
@@ -6843,7 +6840,7 @@ s32 hevc_parse_slice_segment(GF_BitStream *bs, HEVCState *hevc, HEVCSliceInfo *s
 	}

 	pps_id = gf_bs_read_ue_log(bs, "pps_id");
-	if (pps_id >= 64)
+	if ((pps_id<0) || (pps_id >= 64))
 		return -1;

 	pps = &hevc->pps[pps_id];
@@ -7666,7 +7663,7 @@ static s32 gf_hevc_read_vps_bs_internal(GF_BitStream *bs, HEVCState *hevc, Bool
 	//nalu header already parsed
 	vps_id = gf_bs_read_int_log(bs, 4, "vps_id");

-	if (vps_id >= 16) return -1;
+	if ((vps_id<0) || (vps_id >= 16)) return -1;

 	vps = &hevc->vps[vps_id];
 	vps->bit_pos_vps_extensions = -1;
@@ -7895,7 +7892,7 @@ static s32 gf_hevc_read_sps_bs_internal(GF_BitStream *bs, HEVCState *hevc, u8 la

 	//nalu header already parsed
 	vps_id = gf_bs_read_int_log(bs, 4, "vps_id");
-	if (vps_id >= 16) {
+	if ((vps_id<0) || (vps_id >= 16)) {
 		return -1;
 	}
 	memset(&ptl, 0, sizeof(ptl));
@@ -8210,7 +8207,7 @@ static s32 gf_hevc_read_pps_bs_internal(GF_BitStream *bs, HEVCState *hevc)
 		pps->state = 1;
 	}
 	pps->sps_id = gf_bs_read_ue_log(bs, "sps_id");
-	if (pps->sps_id >= 16) {
+	if ((pps->sps_id<0) || (pps->sps_id >= 16)) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[HEVC] wrong SPS ID %d in PPS\n", pps->sps_id));
 		pps->sps_id=0;
 		return -1;
@@ -9360,7 +9357,7 @@ static s32 gf_media_vvc_read_vps_bs_internal(GF_BitStream *bs, VVCState *vvc, Bo

 	//nalu header already parsed
 	vps_id = gf_bs_read_int_log(bs, 4, "vps_id");
-	if (vps_id >= 16) return -1;
+	if ((vps_id<0) || (vps_id >= 16)) return -1;
 	if (!vps_id) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[VVC] VPS ID 0 is forbidden\n"));
 		return -1;
@@ -9451,11 +9448,11 @@ static s32 gf_media_vvc_read_sps_bs_internal(GF_BitStream *bs, VVCState *vvc, u8
 	if (vui_flag_pos) *vui_flag_pos = 0;

 	sps_id = gf_bs_read_int_log(bs, 4, "sps_id");
-	if (sps_id >= 16) {
+	if ((sps_id<0) || (sps_id >= 16)) {
 		return -1;
 	}
 	vps_id = gf_bs_read_int_log(bs, 4, "vps_id");
-	if (vps_id >= 16) {
+	if ((vps_id<0) || (vps_id >= 16)) {
 		return -1;
 	}
 	if (!vps_id && !vvc->vps[0].state) {
@@ -9657,7 +9654,7 @@ static s32 gf_media_vvc_read_pps_bs_internal(GF_BitStream *bs, VVCState *vvc)
 		pps->state = 1;
 	}
 	pps->sps_id = gf_bs_read_int_log(bs, 4, "sps_id");
-	if (pps->sps_id >= 16) {
+	if ((pps->sps_id<0) || (pps->sps_id >= 16)) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[VVC] wrong SPS ID %d in PPS\n", pps->sps_id));
 		pps->sps_id=0;
 		return -1;
@@ -9725,7 +9722,7 @@ s32 vvc_parse_picture_header(GF_BitStream *bs, VVCState *vvc, VVCSliceInfo *si)
 		si->intra_slice_allowed_flag = gf_bs_read_int_log(bs, 1, "intra_slice_allowed_flag");

 	pps_id = gf_bs_read_ue_log(bs, "pps_id");
-	if (pps_id >= 64)
+	if ((pps_id<0) || (pps_id >= 64))
 		return -1;
 	si->pps = &vvc->pps[pps_id];
 	si->sps = &vvc->sps[si->pps->sps_id];


@@ -1035,10 +1035,13 @@ GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, GF_MovieFragment
 				if ((aux_info_type == GF_ISOM_CENC_SCHEME) || (aux_info_type == GF_ISOM_CBC_SCHEME) ||
 					(aux_info_type == GF_ISOM_CENS_SCHEME) || (aux_info_type == GF_ISOM_CBCS_SCHEME) ||
 					(gf_list_count(traf->sai_offsets) == 1)) {
-					offset = saio->offsets[0] + moof_offset;
-					nb_saio = saio->entry_count;
-					break;
+					if (saio->offsets && saio->entry_count) {
+						offset = saio->offsets[0] + moof_offset;
+						nb_saio = saio->entry_count;
+						break;
+					}
 				}
+				saio = NULL;
 			}
 			for (i = 0; i < gf_list_count(traf->sai_sizes); i++) {
 				saiz = (GF_SampleAuxiliaryInfoSizeBox *)gf_list_get(traf->sai_sizes, i);
@@ -1050,6 +1053,7 @@ GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, GF_MovieFragment
 					(gf_list_count(traf->sai_sizes) == 1)) {
 					break;
 				}
+				saiz = NULL;
 			}
 			if (saiz && saio && senc) {
 				for (i = 0; i < saiz->sample_count; i++) {


New functions ecc_mod_mul_canonical and ecc_mod_sqr_canonical.

* ecc-mod-arith.c (ecc_mod_mul_canonical, ecc_mod_sqr_canonical):
New functions.
* ecc-internal.h: Declare and document new functions.
* curve448-eh-to-x.c (curve448_eh_to_x): Use ecc_mod_sqr_canonical.
* curve25519-eh-to-x.c (curve25519_eh_to_x): Use ecc_mod_mul_canonical.
* ecc-eh-to-a.c (ecc_eh_to_a): Likewise.
* ecc-j-to-a.c (ecc_j_to_a): Likewise.
* ecc-mul-m.c (ecc_mul_m): Likewise.

(cherry picked from commit 2bf497ba4d6acc6f352bca015837fad33008565c)

@@ -52,7 +52,6 @@ curve448_eh_to_x (mp_limb_t *xp, const mp_limb_t *p, mp_limb_t *scratch)
 #define tp (scratch + ecc->p.size)

   const struct ecc_curve *ecc = &_nettle_curve448;
-  mp_limb_t cy;

   /* If u = U/W and v = V/W are the coordinates of the point on
      edwards448 we get the curve448 x coordinate as
@@ -62,10 +61,8 @@ curve448_eh_to_x (mp_limb_t *xp, const mp_limb_t *p, mp_limb_t *scratch)
   /* Needs a total of 5*size storage. */
   ecc->p.invert (&ecc->p, t0, up, tp);
   ecc_mod_mul (&ecc->p, t0, t0, vp, tp);
-  ecc_mod_sqr (&ecc->p, t0, t0, tp);
+  ecc_mod_sqr_canonical (&ecc->p, xp, t0, tp);

-  cy = mpn_sub_n (xp, t0, ecc->p.m, ecc->p.size);
-  cnd_copy (cy, xp, t0, ecc->p.size);
 #undef up
 #undef vp
 #undef t0


vtls: add 'isproxy' argument to Curl_ssl_get/addsessionid()

To make sure we set and extract the correct session.

Reported-by: Mingtao Yang
Bug: https://curl.se/docs/CVE-2021-22890.html

CVE-2021-22890

@@ -261,7 +261,9 @@ mesalink_connect_step1(struct Curl_easy *data,
     void *ssl_sessionid = NULL;

     Curl_ssl_sessionid_lock(data);
-    if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
+    if(!Curl_ssl_getsessionid(data, conn,
+                              SSL_IS_PROXY() ? TRUE : FALSE,
+                              &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
       if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(data);
@@ -345,13 +347,14 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
     bool incache;
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
+    bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;

     our_ssl_sessionid = SSL_get_session(BACKEND->handle);

     Curl_ssl_sessionid_lock(data);
     incache =
-      !(Curl_ssl_getsessionid(data, conn,
-                              &old_ssl_sessionid, NULL, sockindex));
+      !(Curl_ssl_getsessionid(data, conn, isproxy, &old_ssl_sessionid, NULL,
+                              sockindex));
     if(incache) {
       if(old_ssl_sessionid != our_ssl_sessionid) {
         infof(data, "old SSL session ID is stale, removing\n");
@@ -361,8 +364,9 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
     }

     if(!incache) {
-      result = Curl_ssl_addsessionid(
-        data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
+      result =
+        Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, 0,
+                              sockindex);
       if(result) {
         Curl_ssl_sessionid_unlock(data);
         failf(data, "failed to store ssl session");


Fix permission checks on constraint violation errors on partitions.

If a cross-partition UPDATE violates a constraint on the target partition,
and the columns in the new partition are in different physical order than
in the parent, the error message can reveal columns that the user does not
have SELECT permission on. A similar bug was fixed earlier in commit
804b6b6db4.

The cause of the bug is that the callers of the
ExecBuildSlotValueDescription() function got confused when constructing
the list of modified columns. If the tuple was routed from a parent, we
converted the tuple to the parent's format, but the list of modified
columns was grabbed directly from the child's RTE entry.

ExecUpdateLockMode() had a similar issue. That lead to confusion on which
columns are key columns, leading to wrong tuple lock being taken on tables
referenced by foreign keys, when a row is updated with INSERT ON CONFLICT
UPDATE. A new isolation test is added for that corner case.

With this patch, the ri_RangeTableIndex field is no longer set for
partitions that don't have an entry in the range table. Previously, it was
set to the RTE entry of the parent relation, but that was confusing.

NOTE: This modifies the ResultRelInfo struct, replacing the
ri_PartitionRoot field with ri_RootResultRelInfo. That's a bit risky to
backpatch, because it breaks any extensions accessing the field. The
change that ri_RangeTableIndex is not set for partitions could potentially
break extensions, too. The ResultRelInfos are visible to FDWs at least,
and this patch required small changes to postgres_fdw. Nevertheless, this
seem like the least bad option. I don't think these fields widely used in
extensions; I don't think there are FDWs out there that uses the FDW
"direct update" API, other than postgres_fdw. If there is, you will get a
compilation error, so hopefully it is caught quickly.

Backpatch to 11, where support for both cross-partition UPDATEs, and unique
indexes on partitioned tables, were added.

Reviewed-by: Amit Langote
Security: CVE-2021-3393

@@ -2804,6 +2804,7 @@ CopyFrom(CopyState cstate)
 	mtstate->ps.state = estate;
 	mtstate->operation = CMD_INSERT;
 	mtstate->resultRelInfo = estate->es_result_relations;
+	mtstate->rootResultRelInfo = estate->es_result_relations;

 	if (resultRelInfo->ri_FdwRoutine != NULL &&
 		resultRelInfo->ri_FdwRoutine->BeginForeignInsert != NULL)


Issue 4711 - SIGSEV with sync_repl (#4738)

Bug description:
	sync_repl sends back entries identified with a unique
	identifier that is 'nsuniqueid'. If 'nsuniqueid' is
	missing, then it may crash

Fix description:
	Check a nsuniqueid is available else returns OP_ERR

relates: https://github.com/389ds/389-ds-base/issues/4711

Reviewed by: Pierre Rogier, James Chapman, William Brown (Thanks!)

Platforms tested:  F33

@@ -165,8 +165,8 @@ sync_create_state_control(Slapi_Entry *e, LDAPControl **ctrlp, int type, Sync_Co
     BerElement *ber;
     struct berval *bvp;
     char *uuid;
-    Slapi_Attr *attr;
-    Slapi_Value *val;
+    Slapi_Attr *attr = NULL;
+    Slapi_Value *val = NULL;

     if (type == LDAP_SYNC_NONE || ctrlp == NULL || (ber = der_alloc()) == NULL) {
         return (LDAP_OPERATIONS_ERROR);
@@ -191,6 +191,14 @@ sync_create_state_control(Slapi_Entry *e, LDAPControl **ctrlp, int type, Sync_Co
     } else {
         slapi_entry_attr_find(e, SLAPI_ATTR_UNIQUEID, &attr);
         slapi_attr_first_value(attr, &val);
+        if ((attr == NULL) || (val == NULL)) {
+            /* It may happen with entries in special backends
+             * such like cn=config, cn=shema, cn=monitor...
+             */
+            slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
+                          "sync_create_state_control - Entries are missing nsuniqueid. Unable to proceed.\n");
+            return (LDAP_OPERATIONS_ERROR);
+        }
         uuid = sync_nsuniqueid2uuid(slapi_value_get_string(val));
     }


Bug 1636771 - Fix incorrect call to Chacha20Poly1305 by PKCS11. r=jcj,kjacobs,rrelyea

Differential Revision: https://phabricator.services.mozilla.com/D74801

--HG--
extra : moz-landing-system : lando

@@ -81,7 +81,7 @@ ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
         PORT_SetError(SEC_ERROR_BAD_KEY);
         return SECFailure;
     }
-    if (tagLen == 0 || tagLen > 16) {
+    if (tagLen != 16) {
         PORT_SetError(SEC_ERROR_INPUT_LEN);
         return SECFailure;
     }


net/ieee802154: Drop fragmented packet if first frag is not present

Bogus fragmented packet could be sent without a FRAG1 fragment and hit
reassembly. Let's make sure this does not happen.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>

@@ -472,6 +472,11 @@ static inline void fragment_reconstruct_packet(struct net_pkt *pkt)
 	fragment_remove_headers(pkt);
 }

+static inline bool fragment_packet_valid(struct net_pkt *pkt)
+{
+	return (get_datagram_type(pkt->buffer->data) == NET_6LO_DISPATCH_FRAG1);
+}
+
 /**
  *  Parse size and tag from the fragment, check if we have any cache
  *  related to it. If not create a new cache.
@@ -537,11 +542,14 @@ static inline enum net_verdict fragment_add_to_cache(struct net_pkt *pkt)
 			cache->pkt = NULL;
 		}

+		clear_reass_cache(size, tag);

-		fragment_reconstruct_packet(pkt);
+		if (!fragment_packet_valid(pkt)) {
+			NET_ERR("Invalid fragmented packet");
+			return NET_DROP;
+		}

-		/* Once reassemble is done, cache is no longer needed. */
-		clear_reass_cache(size, tag);
+		fragment_reconstruct_packet(pkt);

 		if (!net_6lo_uncompress(pkt)) {
 			NET_ERR("Could not uncompress. Bogus packet?");


@@ -2347,8 +2347,8 @@ MagickExport MagickBooleanType PosterizeImage(Image *image,const size_t levels,
   const DitherMethod dither_method,ExceptionInfo *exception)
 {
 #define PosterizeImageTag  "Posterize/Image"
-#define PosterizePixel(pixel) (Quantum) (QuantumRange*(MagickRound( \
-  QuantumScale*pixel*(levels-1)))/MagickMax((ssize_t) levels-1,1))
+#define PosterizePixel(pixel) ClampToQuantum((MagickRealType) QuantumRange*( \
+  MagickRound(QuantumScale*pixel*(levels-1)))/MagickMax((ssize_t) levels-1,1))

   CacheView
     *image_view;
@@ -3282,17 +3282,21 @@ extern "C" {

 static int IntensityCompare(const void *x,const void *y)
 {
+  double
+    intensity;
+
   PixelInfo
     *color_1,
     *color_2;

-  ssize_t
-    intensity;
-
   color_1=(PixelInfo *) x;
   color_2=(PixelInfo *) y;
-  intensity=(ssize_t) (GetPixelInfoIntensity((const Image *) NULL,color_1)-
-    GetPixelInfoIntensity((const Image *) NULL,color_2));
+  intensity=GetPixelInfoIntensity((const Image *) NULL,color_1)-
+    GetPixelInfoIntensity((const Image *) NULL,color_2);
+  if (intensity > (double) INT_MAX)
+    intensity=(double) INT_MAX;
+  if (intensity < (double) INT_MIN)
+    intensity=(double) INT_MIN;
   return((int) intensity);
 }


CVE-2021-20277 ldb/attrib_handlers casefold: stay in bounds

For a string that had N spaces at the beginning, we would
try to move N bytes beyond the end of the string.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14655

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>

(cherry-picked from commit for master)

@@ -76,7 +76,7 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,

 	/* remove leading spaces if any */
 	if (*s == ' ') {
-		for (t = s; *s == ' '; s++) ;
+		for (t = s; *s == ' '; s++, l--) ;

 		/* remove leading spaces by moving down the string */
 		memmove(t, s, l);


@@ -93,10 +93,10 @@ uint8_t ethereum_extractThorchainData(const EthereumSignTx *msg,
   // offset = deposit function hash + address + address + uint256
   uint16_t offset = 4 + (5 * 32);
   int16_t len = msg->data_length - offset;
-  if (msg->has_data_length && len > 0) {
+  if (msg->has_data_length && len > 0 && len < 256) {
     memcpy(buffer, msg->data_initial_chunk.bytes + offset, len);
     // String length must be < 255 characters
-    return len < 256 ? (uint8_t)len : 0;
+    return (uint8_t)len;
   }
   return 0;
 }


libsepol/cil: Check for statements not allowed in optional blocks

While there are some checks for invalid statements in an optional
block when resolving the AST, there are no checks when building the
AST.

OSS-Fuzz found the following policy which caused a null dereference
in cil_tree_get_next_path().
  (blockinherit b3)
  (sid SID)
  (sidorder(SID))
  (optional o
    (ibpkeycon :(1 0)s)
    (block b3
      (filecon""block())
      (filecon""block())))

The problem is that the blockinherit copies block b3 before
the optional block is disabled. When the optional is disabled,
block b3 is deleted along with everything else in the optional.
Later, when filecon statements with the same path are found an
error message is produced and in trying to find out where the block
was copied from, the reference to the deleted block is used. The
error handling code assumes (rightly) that if something was copied
from a block then that block should still exist.

It is clear that in-statements, blocks, and macros cannot be in an
optional, because that allows nodes to be copied from the optional
block to somewhere outside even though the optional could be disabled
later. When optionals are disabled the AST is reset and the
resolution is restarted at the point of resolving macro calls, so
anything resolved before macro calls will never be re-resolved.
This includes tunableifs, in-statements, blockinherits,
blockabstracts, and macro definitions. Tunable declarations also
cannot be in an optional block because they are needed to resolve
tunableifs. It should be fine to allow blockinherit statements in
an optional, because that is copying nodes from outside the optional
to the optional and if the optional is later disabled, everything
will be deleted anyway.

Check and quit with an error if a tunable declaration, in-statement,
block, blockabstract, or macro definition is found within an
optional when either building or resolving the AST.

Signed-off-by: James Carter <jwcart2@gmail.com>

@@ -3808,8 +3808,10 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished

 	if (optional != NULL) {
 		if (node->flavor == CIL_TUNABLE ||
+			node->flavor == CIL_IN ||
+			node->flavor == CIL_BLOCK ||
+			node->flavor == CIL_BLOCKABSTRACT ||
 		    node->flavor == CIL_MACRO) {
-			/* tuanbles and macros are not allowed in optionals*/
 			cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node));
 			rc = SEPOL_ERR;
 			goto exit;


Remove Python training scripts which were moved to tesstrain

Signed-off-by: Stefan Weil <sw@weilnetz.de>

@@ -1,112 +0,0 @@
-#!/usr/bin/env python3
-
-# (C) Copyright 2014, Google Inc.
-# (C) Copyright 2018, James R Barlow
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# http://www.apache.org/licenses/LICENSE-2.0
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# This script provides an easy way to execute various phases of training
-# Tesseract.  For a detailed description of the phases, see
-# https://tesseract-ocr.github.io/tessdoc/Training-Tesseract.html.
-
-import logging
-import os
-import sys
-
-if (sys.version_info.major < 3) or (sys.version_info.major == 3 and sys.version_info.minor < 6):
-    raise Exception("Must be using Python minimum version 3.6!")
-
-sys.path.insert(0, os.path.dirname(__file__))
-from tesstrain_utils import (
-    parse_flags,
-    initialize_fontconfig,
-    phase_I_generate_image,
-    phase_UP_generate_unicharset,
-    phase_E_extract_features,
-    make_lstmdata,
-    cleanup,
-)
-import language_specific
-
-log = logging.getLogger()
-
-
-def setup_logging_console():
-    log.setLevel(logging.DEBUG)
-    console = logging.StreamHandler()
-    console.setLevel(logging.INFO)
-    console_formatter = logging.Formatter(
-        "[%(asctime)s] %(levelname)s - %(message)s", datefmt="%H:%M:%S"
-    )
-    console.setFormatter(console_formatter)
-    log.addHandler(console)
-
-
-def setup_logging_logfile(logfile):
-    logfile = logging.FileHandler(logfile, encoding='utf-8')
-    logfile.setLevel(logging.DEBUG)
-    logfile_formatter = logging.Formatter(
-        "[%(asctime)s] - %(levelname)s - %(name)s - %(message)s"
-    )
-    logfile.setFormatter(logfile_formatter)
-    log.addHandler(logfile)
-    return logfile
-
-
-def main():
-    setup_logging_console()
-    ctx = parse_flags()
-    logfile = setup_logging_logfile(ctx.log_file)
-    if not ctx.linedata:
-        log.error("--linedata_only is required since only LSTM is supported")
-        sys.exit(1)
-
-    log.info(f"=== Starting training for language {ctx.lang_code}")
-    ctx = language_specific.set_lang_specific_parameters(ctx, ctx.lang_code)
-
-    initialize_fontconfig(ctx)
-    phase_I_generate_image(ctx, par_factor=8)
-    phase_UP_generate_unicharset(ctx)
-
-    if ctx.linedata:
-        phase_E_extract_features(ctx, ["lstm.train"], "lstmf")
-        make_lstmdata(ctx)
-
-    log.removeHandler(logfile)
-    logfile.close()
-    cleanup(ctx)
-    log.info("All done!")
-    return 0
-
-
-if __name__ == "__main__":
-    main()
-
-# _rc0 = subprocess.call(["tlog","\n=== Starting training for language '"+str(LANG_CODE.val)+"'"],shell=True)
-# _rc0 = subprocess.call(["source",os.popen("dirname "+__file__).read().rstrip("\n")+"/language-specific.sh"],shell=True)
-# _rc0 = subprocess.call(["set_lang_specific_parameters",str(LANG_CODE.val)],shell=True)
-# _rc0 = subprocess.call(["initialize_fontconfig"],shell=True)
-# _rc0 = subprocess.call(["phase_I_generate_image","8"],shell=True)
-# _rc0 = subprocess.call(["phase_UP_generate_unicharset"],shell=True)
-# if (LINEDATA ):
-# subprocess.call(["phase_E_extract_features"," --psm 6  lstm.train ","8","lstmf"],shell=True)
-#     subprocess.call(["make__lstmdata"],shell=True)
-#     subprocess.call(["tlog","\nCreated starter traineddata for language '"+str(LANG_CODE.val)+"'\n"],shell=True)
-#     subprocess.call(["tlog","\nRun lstmtraining to do the LSTM training for language '"+str(LANG_CODE.val)+"'\n"],shell=True)
-# else:
-#     subprocess.call(["phase_D_generate_dawg"],shell=True)
-#     subprocess.call(["phase_E_extract_features","box.train","8","tr"],shell=True)
-#     subprocess.call(["phase_C_cluster_prototypes",str(TRAINING_DIR.val)+"/"+str(LANG_CODE.val)+".normproto"],shell=True)
-#     if (str(ENABLE_SHAPE_CLUSTERING.val) == "y" ):
-#         subprocess.call(["phase_S_cluster_shapes"],shell=True)
-#     subprocess.call(["phase_M_cluster_microfeatures"],shell=True)
-#     subprocess.call(["phase_B_generate_ambiguities"],shell=True)
-#     subprocess.call(["make__traineddata"],shell=True)
-#     subprocess.call(["tlog","\nCompleted training for language '"+str(LANG_CODE.val)+"'\n"],shell=True)


lib-smtp: smtp-server-connection - Fix STARTTLS command injection vulnerability.

The input handler kept reading more commands even though the input was locked by
the STARTTLS command, thereby causing it to read the command pipelined beyond
STARTTLS. This causes a STARTTLS command injection vulerability.

@@ -37,6 +37,13 @@ static int cmd_starttls_start(struct smtp_server_connection *conn)
 		return -1;
 	}

+	/* The command queue must be empty at this point. If anything were to be
+	   queued somehow, this connection is vulnerable to STARTTLS command
+	   insertion.
+	 */
+	i_assert(conn->command_queue_count == 0 &&
+		 conn->command_queue_head == NULL);
+
 	/* RFC 3207, Section 4.2:

 	   Upon completion of the TLS handshake, the SMTP protocol is reset to
@@ -107,6 +114,13 @@ cmd_starttls_next(struct smtp_server_cmd_ctx *cmd, void *context ATTR_UNUSED)
 	const struct smtp_server_callbacks *callbacks = conn->callbacks;
 	int ret;

+	/* The command queue can only contain the STARTTLS command at this
+	   point. If anything beyond the STARTTLS were queued somehow, this
+	   connection is vulnerable to STARTTLS command insertion.
+	 */
+	i_assert(conn->command_queue_count == 1 &&
+	         conn->command_queue_tail == command);
+
 	smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_STARTTLS,
 					 NULL);


Merge pull request #15945 from nmeum/pr/clif_get_attr_bounds

clif: After incrementing pos, make sure it is still in bounds

@@ -278,7 +278,10 @@ ssize_t clif_get_attr(const char *input, size_t input_len, clif_attr_t *attr)
             attr->key_len = pos - attr->key;
             /* check if the value is quoted and prepare pointer for value scan */
             pos++;
-            if (*pos == '"') {
+            if (pos == end) {
+                break;
+            }
+            else if (*pos == '"') {
                 quoted = true;
                 pos++;
             }


openssl: associate/detach the transfer from connection

CVE-2021-22901

Bug: https://curl.se/docs/CVE-2021-22901.html

@@ -1304,7 +1304,9 @@ const struct Curl_ssl Curl_ssl_gskit = {
   Curl_none_set_engine_default,   /* set_engine_default */
   Curl_none_engines_list,         /* engines_list */
   Curl_none_false_start,          /* false_start */
-  NULL                            /* sha256sum */
+  NULL,                           /* sha256sum */
+  NULL,                           /* associate_connection */
+  NULL                            /* disassociate_connection */
 };

 #endif /* USE_GSKIT */


@@ -84,6 +84,11 @@ struct Curl_ssl {
   bool (*false_start)(void);
   CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
                     unsigned char *sha256sum, size_t sha256sumlen);
+
+  void (*associate_connection)(struct Curl_easy *data,
+                               struct connectdata *conn,
+                               int sockindex);
+  void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
 };

 #ifdef USE_SSL
@@ -283,6 +288,11 @@ bool Curl_ssl_cert_status_request(void);

 bool Curl_ssl_false_start(void);

+void Curl_ssl_associate_conn(struct Curl_easy *data,
+                             struct connectdata *conn);
+void Curl_ssl_detach_conn(struct Curl_easy *data,
+                          struct connectdata *conn);
+
 #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */

 #else /* if not USE_SSL */
@@ -309,6 +319,8 @@ bool Curl_ssl_false_start(void);
 #define Curl_ssl_cert_status_request() FALSE
 #define Curl_ssl_false_start() FALSE
 #define Curl_ssl_tls13_ciphersuites() FALSE
+#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt
+#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt
 #endif

 #endif /* HEADER_CURL_VTLS_H */


Use size_t for DWA buffersize calculation (#901)

* Use size_t for DWA buffersize calculation

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>

* use Int64 instead of size_t for buffersize calculations

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>

@@ -2932,10 +2932,10 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
     // of channels we have.
     //

-    size_t maxOutBufferSize  = 0;
+    Int64 maxOutBufferSize  = 0;
     int numLossyDctChans  = 0;
-    int unknownBufferSize = 0;
-    int rleBufferSize     = 0;
+    Int64 unknownBufferSize = 0;
+    Int64 rleBufferSize     = 0;

     int maxLossyDctAcSize = (int)ceil ((float)numScanLines() / 8.0f) *
                             (int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) *
@@ -2945,6 +2945,8 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
                             (int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) *
                             sizeof (unsigned short);

+    Int64 pixelCount = static_cast<Int64>(numScanLines()) * static_cast<Int64>(_max[0] - _min[0] + 1);
+
     for (unsigned int chan = 0; chan < _channelData.size(); ++chan)
     {
         switch (_channelData[chan].compression)
@@ -2971,8 +2973,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
                 // of the source data.
                 //

-                int rleAmount = 2 * numScanLines() * (_max[0] - _min[0] + 1) *
-                                OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
+                Int64 rleAmount = 2 * pixelCount * OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);

                 rleBufferSize += rleAmount;
             }
@@ -2981,8 +2982,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)

           case UNKNOWN:

-            unknownBufferSize += numScanLines() * (_max[0] - _min[0] + 1) *
-                                 OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
+            unknownBufferSize += pixelCount * OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
             break;

           default:
@@ -2999,13 +2999,13 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
     // which could take slightly more space
     //

-    maxOutBufferSize += compressBound ((uLongf)rleBufferSize);
+    maxOutBufferSize += compressBound (rleBufferSize);

     //
     // And the same goes for the UNKNOWN data
     //

-    maxOutBufferSize += compressBound ((uLongf)unknownBufferSize);
+    maxOutBufferSize += compressBound (unknownBufferSize);

     //
     // Allocate a zip/deflate compressor big enought to hold the DC data
@@ -3052,7 +3052,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
     // to Huffman encoding
     //

-    if (static_cast<size_t>(maxLossyDctAcSize * numLossyDctChans) > _packedAcBufferSize)
+    if (static_cast<Int64>(maxLossyDctAcSize * numLossyDctChans) > _packedAcBufferSize)
     {
         _packedAcBufferSize = maxLossyDctAcSize * numLossyDctChans;
         if (_packedAcBuffer != 0)
@@ -3064,15 +3064,15 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
     // _packedDcBuffer holds one quantized DCT coef per 8x8 block
     //

-    if (static_cast<size_t>(maxLossyDctDcSize * numLossyDctChans) > _packedDcBufferSize)
+    if (static_cast<Int64>(maxLossyDctDcSize * numLossyDctChans) > _packedDcBufferSize)
     {
         _packedDcBufferSize = maxLossyDctDcSize * numLossyDctChans;
         if (_packedDcBuffer != 0)
             delete[] _packedDcBuffer;
         _packedDcBuffer     = new char[_packedDcBufferSize];
     }

-    if (static_cast<size_t>(rleBufferSize) > _rleBufferSize)
+    if ( rleBufferSize > _rleBufferSize )
     {
         _rleBufferSize = rleBufferSize;
         if (_rleBuffer != 0)
@@ -3091,7 +3091,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
     // all in one swoop (for each compression scheme).
     //

-    int planarUncBufferSize[NUM_COMPRESSOR_SCHEMES];
+    Int64 planarUncBufferSize[NUM_COMPRESSOR_SCHEMES];
     for (int i=0; i<NUM_COMPRESSOR_SCHEMES; ++i)
         planarUncBufferSize[i] = 0;

@@ -3103,14 +3103,12 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
             break;

           case RLE:
-            planarUncBufferSize[RLE] +=
-                     numScanLines() * (_max[0] - _min[0] + 1) *
+            planarUncBufferSize[RLE] += pixelCount *
                      OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
             break;

           case UNKNOWN:
-            planarUncBufferSize[UNKNOWN] +=
-                     numScanLines() * (_max[0] - _min[0] + 1) *
+            planarUncBufferSize[UNKNOWN] += pixelCount *
                      OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type);
             break;

@@ -3128,16 +3126,22 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
     if (planarUncBufferSize[UNKNOWN] > 0)
     {
         planarUncBufferSize[UNKNOWN] =
-            compressBound ((uLongf)planarUncBufferSize[UNKNOWN]);
+            compressBound (planarUncBufferSize[UNKNOWN]);
     }

     for (int i = 0; i < NUM_COMPRESSOR_SCHEMES; ++i)
     {
-        if (static_cast<size_t>(planarUncBufferSize[i]) > _planarUncBufferSize[i])
+        if ( planarUncBufferSize[i] > _planarUncBufferSize[i])
         {
             _planarUncBufferSize[i] = planarUncBufferSize[i];
             if (_planarUncBuffer[i] != 0)
                 delete[] _planarUncBuffer[i];
+
+            if (planarUncBufferSize[i] > std::numeric_limits<size_t>::max())
+            {
+                throw IEX_NAMESPACE::ArgExc("DWA buffers too large");
+            }
+
             _planarUncBuffer[i] = new char[planarUncBufferSize[i]];
         }
     }


tame some window operations, just in case

@@ -2552,6 +2552,7 @@ do_winop(void)
         win_maximise(0);
         win_set_chars(rows0, cols0);
       }
+      usleep(1000);
     }
     when 10:
       if (term.csi_argc != 2)
@@ -2563,6 +2564,7 @@ do_winop(void)
         win_maximise(-2);
       else if (arg1 == 1 || arg1 == 0)
         win_maximise(arg1 ? 2 : 0);
+      usleep(1000);
     when 11: child_write(win_is_iconic() ? "\e[2t" : "\e[1t", 4);
     when 13: {
       int x, y;


Prevent integer overflows in array subscripting calculations.

While we were (mostly) careful about ensuring that the dimensions of
arrays aren't large enough to cause integer overflow, the lower bound
values were generally not checked.  This allows situations where
lower_bound + dimension overflows an integer.  It seems that that's
harmless so far as array reading is concerned, except that array
elements with subscripts notionally exceeding INT_MAX are inaccessible.
However, it confuses various array-assignment logic, resulting in a
potential for memory stomps.

Fix by adding checks that array lower bounds aren't large enough to
cause lower_bound + dimension to overflow.  (Note: this results in
disallowing cases where the last subscript position would be exactly
INT_MAX.  In principle we could probably allow that, but there's a lot
of code that computes lower_bound + dimension and would need adjustment.
It seems doubtful that it's worth the trouble/risk to allow it.)

Somewhat independently of that, array_set_element() was careless
about possible overflow when checking the subscript of a fixed-length
array, creating a different route to memory stomps.  Fix that too.

Security: CVE-2021-32027

@@ -2811,6 +2811,10 @@ ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op)
 			lbs[i] = elem_lbs[i - 1];
 		}

+		/* check for subscript overflow */
+		(void) ArrayGetNItems(ndims, dims);
+		ArrayCheckBounds(ndims, dims, lbs);
+
 		if (havenulls)
 		{
 			dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems);


Merge pull request from GHSA-cv8x-p47p-99wr

* - Avoid SSL socket parent/listener getting destroyed during handshake by increasing parent's reference count.
- Add missing SSL socket close when the newly accepted SSL socket is discarded in SIP TLS transport.

* - Fix silly mistake: accepted active socket created without group lock in SSL socket.
- Replace assertion with normal validation check of SSL socket instance in OpenSSL verification callback (verify_cb()) to avoid crash, e.g: if somehow race condition with SSL socket destroy happens or OpenSSL application data index somehow gets corrupted.

@@ -1333,9 +1333,26 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
     PJ_UNUSED_ARG(src_addr_len);

     listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);
+    if (!listener) {
+	/* Listener already destroyed, e.g: after TCP accept but before SSL
+	 * handshake is completed.
+	 */
+	if (new_ssock && accept_status == PJ_SUCCESS) {
+	    /* Close the SSL socket if the accept op is successful */
+	    PJ_LOG(4,(THIS_FILE,
+		      "Incoming TLS connection from %s (sock=%d) is discarded "
+		      "because listener is already destroyed",
+		      pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
+		      new_ssock));
+
+	    pj_ssl_sock_close(new_ssock);
+	}
+
+	return PJ_FALSE;
+    }

     if (accept_status != PJ_SUCCESS) {
-	if (listener && listener->tls_setting.on_accept_fail_cb) {
+	if (listener->tls_setting.on_accept_fail_cb) {
 	    pjsip_tls_on_accept_fail_param param;
 	    pj_ssl_sock_info ssi;

@@ -1358,6 +1375,8 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
     PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);

     if (!listener->is_registered) {
+	pj_ssl_sock_close(new_ssock);
+
 	if (listener->tls_setting.on_accept_fail_cb) {
 	    pjsip_tls_on_accept_fail_param param;
 	    pj_bzero(&param, sizeof(param));
@@ -1409,6 +1428,8 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
 			 ssl_info.grp_lock, &tls);

     if (status != PJ_SUCCESS) {
+	pj_ssl_sock_close(new_ssock);
+
 	if (listener->tls_setting.on_accept_fail_cb) {
 	    pjsip_tls_on_accept_fail_param param;
 	    pj_bzero(&param, sizeof(param));


git_connect_git(): forbid newlines in host and path

When we connect to a git:// server, we send an initial request that
looks something like:

  002dgit-upload-pack repo.git\0host=example.com

If the repo path contains a newline, then it's included literally, and
we get:

  002egit-upload-pack repo
  .git\0host=example.com

This works fine if you really do have a newline in your repository name;
the server side uses the pktline framing to parse the string, not
newlines. However, there are many _other_ protocols in the wild that do
parse on newlines, such as HTTP. So a carefully constructed git:// URL
can actually turn into a valid HTTP request. For example:

  git://localhost:1234/%0d%0a%0d%0aGET%20/%20HTTP/1.1 %0d%0aHost:localhost%0d%0a%0d%0a

becomes:

  0050git-upload-pack /
  GET / HTTP/1.1
  Host:localhost

  host=localhost:1234

on the wire. Again, this isn't a problem for a real Git server, but it
does mean that feeding a malicious URL to Git (e.g., through a
submodule) can cause it to make unexpected cross-protocol requests.
Since repository names with newlines are presumably quite rare (and
indeed, we already disallow them in git-over-http), let's just disallow
them over this protocol.

Hostnames could likewise inject a newline, but this is unlikely a
problem in practice; we'd try resolving the hostname with a newline in
it, which wouldn't work. Still, it doesn't hurt to err on the side of
caution there, since we would not expect them to work in the first
place.

The ssh and local code paths are unaffected by this patch. In both cases
we're trying to run upload-pack via a shell, and will quote the newline
so that it makes it intact. An attacker can point an ssh url at an
arbitrary port, of course, but unless there's an actual ssh server
there, we'd never get as far as sending our shell command anyway.  We
_could_ similarly restrict newlines in those protocols out of caution,
but there seems little benefit to doing so.

The new test here is run alongside the git-daemon tests, which cover the
same protocol, but it shouldn't actually contact the daemon at all.  In
theory we could make the test more robust by setting up an actual
repository with a newline in it (so that our clone would succeed if our
new check didn't kick in). But a repo directory with newline in it is
likely not portable across all filesystems. Likewise, we could check
git-daemon's log that it was not contacted at all, but we do not
currently record the log (and anyway, it would make the test racy with
the daemon's log write). We'll just check the client-side stderr to make
sure we hit the expected code path.

Reported-by: Harold Kim <h.kim@flatt.tech>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

@@ -1063,6 +1063,8 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport,
 		target_host = xstrdup(hostandport);

 	transport_check_allowed("git");
+	if (strchr(target_host, '\n') || strchr(path, '\n'))
+		die(_("newline is forbidden in git:// hosts and repo paths"));

 	/*
 	 * These underlying connection commands die() if they


@@ -46,7 +46,7 @@ GF_Err co64_box_read(GF_Box *s,GF_BitStream *bs)

 	ISOM_DECREASE_SIZE(ptr, 4)

-	if (ptr->nb_entries > ptr->size / 8) {
+	if ((u64)ptr->nb_entries > ptr->size / 8 || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(u64)) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in co64\n", ptr->nb_entries));
 		return GF_ISOM_INVALID_FILE;
 	}
@@ -392,7 +392,7 @@ GF_Err ctts_box_read(GF_Box *s, GF_BitStream *bs)
 	ISOM_DECREASE_SIZE(ptr, 4);
 	ptr->nb_entries = gf_bs_read_u32(bs);

-	if (ptr->nb_entries > ptr->size / 8) {
+	if (ptr->nb_entries > ptr->size / 8 || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(GF_DttsEntry) ) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in ctts\n", ptr->nb_entries));
 		return GF_ISOM_INVALID_FILE;
 	}
@@ -3199,6 +3199,10 @@ GF_Err tfra_box_read(GF_Box *s, GF_BitStream *bs)
 	}

 	if (ptr->nb_entries) {
+		if ((u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(GF_RandomAccessEntry)) {
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in traf\n", ptr->nb_entries));
+			return GF_ISOM_INVALID_FILE;
+		}
 		p = (GF_RandomAccessEntry *) gf_malloc(sizeof(GF_RandomAccessEntry) * ptr->nb_entries);
 		if (!p) return GF_OUT_OF_MEM;
 	}
@@ -5104,7 +5108,7 @@ GF_Err stco_box_read(GF_Box *s, GF_BitStream *bs)

 	ISOM_DECREASE_SIZE(ptr, 4);
 	ptr->nb_entries = gf_bs_read_u32(bs);
-	if (ptr->nb_entries > ptr->size / 4) {
+	if (ptr->nb_entries > ptr->size / 4 || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(u32)) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in stco\n", ptr->nb_entries));
 		return GF_ISOM_INVALID_FILE;
 	}
@@ -5236,7 +5240,7 @@ GF_Err stsc_box_read(GF_Box *s, GF_BitStream *bs)
 	ISOM_DECREASE_SIZE(ptr, 4);
 	ptr->nb_entries = gf_bs_read_u32(bs);

-	if (ptr->nb_entries > ptr->size / 12) {
+	if (ptr->nb_entries > ptr->size / 12 || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(GF_StscEntry)) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in stsc\n", ptr->nb_entries));
 		return GF_ISOM_INVALID_FILE;
 	}
@@ -5575,6 +5579,10 @@ GF_Err stsz_box_read(GF_Box *s, GF_BitStream *bs)
 			}
 		}
 	}
+	if (ptr->sampleCount && (u64)ptr->sampleCount > (u64)SIZE_MAX/sizeof(u32)) {
+		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in stsz\n", ptr->sampleCount));
+		return GF_ISOM_INVALID_FILE;
+	}
 	if (s->type == GF_ISOM_BOX_TYPE_STSZ) {
 		if (! ptr->sampleSize && ptr->sampleCount) {
 			if (ptr->sampleCount > ptr->size / 4) {
@@ -5779,7 +5787,7 @@ GF_Err stts_box_read(GF_Box *s, GF_BitStream *bs)

 	ISOM_DECREASE_SIZE(ptr, 4);
 	ptr->nb_entries = gf_bs_read_u32(bs);
-	if (ptr->size / 8 < ptr->nb_entries) {
+	if (ptr->size / 8 < ptr->nb_entries || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(GF_SttsEntry)) {
 		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in stts\n", ptr->nb_entries));
 		return GF_ISOM_INVALID_FILE;
 	}
@@ -7384,6 +7392,10 @@ GF_Err trun_box_read(GF_Box *s, GF_BitStream *bs)
 		if (ptr->sample_count * 4 > ptr->size) {
 			ISOM_DECREASE_SIZE(ptr, ptr->sample_count*4);
 		}
+		if ((u64)ptr->sample_count > (u64)SIZE_MAX/sizeof(GF_TrunEntry)) {
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of samples %d in trun\n", ptr->sample_count));
+			return GF_ISOM_INVALID_FILE;
+		}
 		ptr->samples = gf_malloc(sizeof(GF_TrunEntry) * ptr->sample_count);
 		if (!ptr->samples) return GF_OUT_OF_MEM;
 		ptr->sample_alloc = ptr->nb_samples = ptr->sample_count;
@@ -8868,7 +8880,7 @@ GF_Err ssix_box_read(GF_Box *s, GF_BitStream *bs)
 	ISOM_DECREASE_SIZE(ptr, 4)
 	ptr->subsegment_count = gf_bs_read_u32(bs);
 	//each subseg has at least one range_count (4 bytes), abort if not enough bytes (broken box)
-	if (ptr->size / 4 < ptr->subsegment_count)
+	if (ptr->size / 4 < ptr->subsegment_count || (u64)ptr->subsegment_count > (u64)SIZE_MAX/sizeof(GF_SubsegmentInfo))
 		return GF_ISOM_INVALID_FILE;

 	ptr->subsegment_alloc = ptr->subsegment_count;
@@ -8880,7 +8892,7 @@ GF_Err ssix_box_read(GF_Box *s, GF_BitStream *bs)
 		ISOM_DECREASE_SIZE(ptr, 4)
 		subseg->range_count = gf_bs_read_u32(bs);
 		//each range is 4 bytes, abort if not enough bytes
-		if (ptr->size / 4 < subseg->range_count)
+		if (ptr->size / 4 < subseg->range_count || (u64)subseg->range_count > (u64)SIZE_MAX/sizeof(GF_SubsegmentRangeInfo))
 			return GF_ISOM_INVALID_FILE;
 		subseg->ranges = (GF_SubsegmentRangeInfo*) gf_malloc(sizeof(GF_SubsegmentRangeInfo) * subseg->range_count);
 		if (!subseg->ranges) return GF_OUT_OF_MEM;
@@ -9062,6 +9074,11 @@ GF_Err pcrb_box_read(GF_Box *s,GF_BitStream *bs)
 	ISOM_DECREASE_SIZE(ptr, 4);
 	ptr->subsegment_count = gf_bs_read_u32(bs);

+	if ((u64)ptr->subsegment_count > ptr->size / 8 || (u64)ptr->subsegment_count > (u64)SIZE_MAX/sizeof(u64)) {
+		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of subsegment %d in pcrb\n", ptr->subsegment_count));
+		return GF_ISOM_INVALID_FILE;
+	}
+
 	ptr->pcr_values = gf_malloc(sizeof(u64)*ptr->subsegment_count);
 	if (!ptr->pcr_values) return GF_OUT_OF_MEM;
 	for (i=0; i<ptr->subsegment_count; i++) {
@@ -9386,7 +9403,7 @@ GF_Err sbgp_box_read(GF_Box *s, GF_BitStream *bs)
 	}
 	ptr->entry_count = gf_bs_read_u32(bs);

-	if (ptr->size < sizeof(GF_SampleGroupEntry)*ptr->entry_count)
+	if (ptr->size < sizeof(GF_SampleGroupEntry)*ptr->entry_count || (u64)ptr->entry_count > (u64)SIZE_MAX/sizeof(GF_SampleGroupEntry))
 	    return GF_ISOM_INVALID_FILE;

 	ptr->sample_entries = gf_malloc(sizeof(GF_SampleGroupEntry)*ptr->entry_count);
@@ -10041,7 +10058,7 @@ GF_Err saio_box_read(GF_Box *s, GF_BitStream *bs)

 	if (ptr->entry_count) {
 		u32 i;
-		if (ptr->size / (ptr->version == 0 ? 4 : 8) < ptr->entry_count)
+		if (ptr->size / (ptr->version == 0 ? 4 : 8) < ptr->entry_count || (u64)ptr->entry_count > (u64)SIZE_MAX/sizeof(u64))
 			return GF_ISOM_INVALID_FILE;
 		ptr->offsets = gf_malloc(sizeof(u64)*ptr->entry_count);
 		if (!ptr->offsets)
@@ -10551,7 +10568,7 @@ GF_Err fpar_box_read(GF_Box *s, GF_BitStream *bs)

 	ISOM_DECREASE_SIZE(ptr, (ptr->version ? 4 : 2) );
 	ptr->nb_entries = gf_bs_read_int(bs, ptr->version ? 32 : 16);
-	if (ptr->nb_entries > ptr->size / 6)
+	if (ptr->nb_entries > ptr->size / 6 || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(FilePartitionEntry))
 		return GF_ISOM_INVALID_FILE;

 	ISOM_DECREASE_SIZE(ptr, ptr->nb_entries * 6 );
@@ -10637,6 +10654,11 @@ GF_Err fecr_box_read(GF_Box *s, GF_BitStream *bs)
 	ISOM_DECREASE_SIZE(ptr, (ptr->version ? 4 : 2) );
 	ptr->nb_entries = gf_bs_read_int(bs, ptr->version ? 32 : 16);

+	if (ptr->nb_entries > ptr->size / (ptr->version ? 8 : 6) || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(FECReservoirEntry) ) {
+		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in fecr\n", ptr->nb_entries));
+		return GF_ISOM_INVALID_FILE;
+	}
+
 	ISOM_DECREASE_SIZE(ptr, ptr->nb_entries * (ptr->version ? 8 : 6) );
 	GF_SAFE_ALLOC_N(ptr->entries, ptr->nb_entries, FECReservoirEntry);
 	if (!ptr->entries) return GF_OUT_OF_MEM;
@@ -12251,8 +12273,10 @@ GF_Err csgp_box_read(GF_Box *s, GF_BitStream *bs)
 	ptr->pattern_count = gf_bs_read_u32(bs);

-	if (ptr->size / ( (pattern_size + scount_size) / 8 ) < ptr->pattern_count )
-	    return GF_ISOM_INVALID_FILE;
+	if ( (ptr->size / ( (pattern_size + scount_size) / 8 ) < ptr->pattern_count) || (u64)ptr->pattern_count > (u64)SIZE_MAX/sizeof(GF_CompactSampleGroupPattern) ) {
+		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] compact sample gorup pattern_count value (%lu) invalid\n", ptr->pattern_count));
+		return GF_ISOM_INVALID_FILE;
+	}

 	ptr->patterns = gf_malloc(sizeof(GF_CompactSampleGroupPattern) * ptr->pattern_count);
 	if (!ptr->patterns) return GF_OUT_OF_MEM;
@@ -12267,6 +12291,11 @@ GF_Err csgp_box_read(GF_Box *s, GF_BitStream *bs)
 			ISOM_DECREASE_SIZE(ptr, bits);
 			bits=0;
 		}
+		if ( (u64)ptr->patterns[i].length > (u64)SIZE_MAX/sizeof(u32) ) {
+			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] compact sample gorup pattern #%d value (%lu) invalid\n", i, ptr->patterns[i].length));
+			ptr->patterns[i].sample_group_description_indices = NULL;
+			return GF_ISOM_INVALID_FILE;
+		}
 		ptr->patterns[i].sample_group_description_indices = gf_malloc(sizeof(u32) * ptr->patterns[i].length);
 		if (!ptr->patterns[i].sample_group_description_indices) return GF_OUT_OF_MEM;
 	}


Merge branch 'master' into 'master'

Fix CVE-2021-39359 by forcing TLS certificate validation

Closes #249

See merge request GNOME/libgda!189

@@ -355,8 +355,8 @@ gda_web_provider_open_connection (GdaServerProvider *provider, GdaConnection *cn
 	g_rec_mutex_init (& (cdata->mutex));
 	cdata->server_id = NULL;
 	cdata->forced_closing = FALSE;
-	cdata->worker_session = soup_session_new ();
-	cdata->front_session = soup_session_new_with_options ("max-conns-per-host", 1, NULL);
+	cdata->worker_session = soup_session_new_with_options ("ssl-use-system-ca-file", TRUE, NULL);
+	cdata->front_session = soup_session_new_with_options ("max-conns-per-host", 1, "ssl-use-system-ca-file", TRUE, NULL);
 	if (use_ssl) {
 		server_url = g_string_new ("https://");
 		g_print ("USING SSL\n");


Fix crash while receiving some kind of invalid from header.

@@ -2,7 +2,7 @@
  *  This C header file was generated by $ANTLR version 3.4
  *
  *     -  From the grammar source file : ../grammars/belle_sip_message.g
- *     -                            On : 2021-05-03 11:52:47
+ *     -                            On : 2021-05-13 15:53:10
  *     -                for the parser : belle_sip_messageParserParser
  *
  * Editing it, at least manually, is not wise.


NFSD: Prevent a possible oops in the nfs_dirent() tracepoint

The double copy of the string is a mistake, plus __assign_str()
uses strlen(), which is wrong to do on a string that isn't
guaranteed to be NUL-terminated.

Fixes: 6019ce0742ca ("NFSD: Add a tracepoint to record directory entry encoding")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

@@ -408,7 +408,6 @@ TRACE_EVENT(nfsd_dirent,
 		__entry->ino = ino;
 		__entry->len = namlen;
 		memcpy(__get_str(name), name, namlen);
-		__assign_str(name, name);
 	),
 	TP_printk("fh_hash=0x%08x ino=%llu name=%.*s",
 		__entry->fh_hash, __entry->ino,


patch 8.2.3409: reading beyond end of line with invalid utf-8 character

Problem:    Reading beyond end of line with invalid utf-8 character.
Solution:   Check for NUL when advancing.

@@ -5664,7 +5664,8 @@ find_match_text(colnr_T startcol, int regstart, char_u *match_text)
 		match = FALSE;
 		break;
 	    }
-	    len2 += MB_CHAR2LEN(c2);
+	    len2 += enc_utf8 ? utf_ptr2len(rex.line + col + len2)
+							     : MB_CHAR2LEN(c2);
 	}
 	if (match
 		// check that no composing char follows


Unsquashfs: additional write outside destination directory exploit fix

An issue on github (https://github.com/plougher/squashfs-tools/issues/72)
showed how some specially crafted Squashfs filesystems containing
invalid file names (with '/' and '..') can cause Unsquashfs to write
files outside of the destination directory.

Since then it has been shown that specially crafted Squashfs filesystems
that contain a symbolic link pointing outside of the destination directory,
coupled with an identically named file within the same directory, can
cause Unsquashfs to write files outside of the destination directory.

Specifically the symbolic link produces a pathname pointing outside
of the destination directory, which is then followed when writing the
duplicate identically named file within the directory.

This commit fixes this exploit by explictly checking for duplicate
filenames within a directory.  As directories in v2.1, v3.x, and v4.0
filesystems are sorted, this is achieved by checking for consecutively
identical filenames.  Additionally directories are checked to
ensure they are sorted, to avoid attempts to evade the duplicate
check.

Version 1.x and 2.0 filesystems (where the directories were unsorted)
are sorted and then the above duplicate filename check is applied.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>

@@ -497,6 +497,12 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
 		}
 	}

+	/* check directory for duplicate names and sorting */
+	if(check_directory(dir) == FALSE) {
+		ERROR("File system corrupted: directory has duplicate names or is unsorted\n");
+		goto corrupted;
+	}
+
 	return dir;

 corrupted:


@@ -2880,23 +2880,27 @@ void DumpTrackInfo(GF_ISOFile *file, GF_ISOTrackID trackID, Bool full_dump, Bool
 		fprintf(stderr, "\tAOM AV1 stream - Resolution %d x %d\n", w, h);

 		av1c = gf_isom_av1_config_get(file, trackNum, 1);
-		fprintf(stderr, "\tversion=%u, profile=%u, level_idx0=%u, tier=%u\n", (u32)av1c->version, (u32)av1c->seq_profile, (u32)av1c->seq_level_idx_0, (u32)av1c->seq_tier_0);
-		fprintf(stderr, "\thigh_bitdepth=%u, twelve_bit=%u, monochrome=%u\n", (u32)av1c->high_bitdepth, (u32)av1c->twelve_bit, (u32)av1c->monochrome);
-		fprintf(stderr, "\tchroma: subsampling_x=%u, subsampling_y=%u, sample_position=%u\n", (u32)av1c->chroma_subsampling_x, (u32)av1c->chroma_subsampling_y, (u32)av1c->chroma_sample_position);
+		if (!av1c) {
+			fprintf(stderr, "\tCorrupted av1 config\n");
+		} else {
+			fprintf(stderr, "\tversion=%u, profile=%u, level_idx0=%u, tier=%u\n", (u32)av1c->version, (u32)av1c->seq_profile, (u32)av1c->seq_level_idx_0, (u32)av1c->seq_tier_0);
+			fprintf(stderr, "\thigh_bitdepth=%u, twelve_bit=%u, monochrome=%u\n", (u32)av1c->high_bitdepth, (u32)av1c->twelve_bit, (u32)av1c->monochrome);
+			fprintf(stderr, "\tchroma: subsampling_x=%u, subsampling_y=%u, sample_position=%u\n", (u32)av1c->chroma_subsampling_x, (u32)av1c->chroma_subsampling_y, (u32)av1c->chroma_sample_position);

-		if (av1c->initial_presentation_delay_present)
-			fprintf(stderr, "\tInitial presentation delay %u\n", (u32) av1c->initial_presentation_delay_minus_one+1);
+			if (av1c->initial_presentation_delay_present)
+				fprintf(stderr, "\tInitial presentation delay %u\n", (u32) av1c->initial_presentation_delay_minus_one+1);

-		count = gf_list_count(av1c->obu_array);
-		for (i=0; i<count; i++) {
-			u8 hash[20];
-			GF_AV1_OBUArrayEntry *obu = gf_list_get(av1c->obu_array, i);
-			gf_sha1_csum((u8*)obu->obu, (u32)obu->obu_length, hash);
-			fprintf(stderr, "\tOBU#%d %s hash: ", i+1, gf_av1_get_obu_name(obu->obu_type) );
-			for (j=0; j<20; j++) fprintf(stderr, "%02X", hash[j]);
-			fprintf(stderr, "\n");
+			count = gf_list_count(av1c->obu_array);
+			for (i=0; i<count; i++) {
+				u8 hash[20];
+				GF_AV1_OBUArrayEntry *obu = gf_list_get(av1c->obu_array, i);
+				gf_sha1_csum((u8*)obu->obu, (u32)obu->obu_length, hash);
+				fprintf(stderr, "\tOBU#%d %s hash: ", i+1, gf_av1_get_obu_name(obu->obu_type) );
+				for (j=0; j<20; j++) fprintf(stderr, "%02X", hash[j]);
+				fprintf(stderr, "\n");
+			}
+			gf_odf_av1_cfg_del(av1c);
 		}
-		gf_odf_av1_cfg_del(av1c);
 	} else if (msub_type == GF_ISOM_SUBTYPE_3GP_H263) {
 		u32 w, h;
 		gf_isom_get_visual_info(file, trackNum, 1, &w, &h);


@@ -674,7 +674,6 @@ GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp,

 GF_Err Media_CheckDataEntry(GF_MediaBox *mdia, u32 dataEntryIndex)
 {
-
 	GF_DataEntryURLBox *entry;
 	GF_DataMap *map;
 	GF_Err e;
@@ -685,8 +684,10 @@ GF_Err Media_CheckDataEntry(GF_MediaBox *mdia, u32 dataEntryIndex)
 	if (entry->flags == 1) return GF_OK;

 	//ok, not self contained, let's go for it...
-	//we don't know what's a URN yet
-	if (entry->type == GF_ISOM_BOX_TYPE_URN) return GF_NOT_SUPPORTED;
+	//we only support alias and URL boxes
+	if ((entry->type != GF_ISOM_BOX_TYPE_URL) && (entry->type != GF_QT_BOX_TYPE_ALIS) )
+		return GF_NOT_SUPPORTED;
+
 	if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_WRITE) {
 		e = gf_isom_datamap_new(entry->location, NULL, GF_ISOM_DATA_MAP_READ, &map);
 	} else {


patch 8.2.3402: invalid memory access when using :retab with large value

Problem:    Invalid memory access when using :retab with large value.
Solution:   Check the number is positive.

@@ -18,18 +18,19 @@
 /*
  * Set the integer values corresponding to the string setting of 'vartabstop'.
  * "array" will be set, caller must free it if needed.
+ * Return FAIL for an error.
  */
     int
 tabstop_set(char_u *var, int **array)
 {
-    int valcount = 1;
-    int t;
-    char_u *cp;
+    int	    valcount = 1;
+    int	    t;
+    char_u  *cp;

     if (var[0] == NUL || (var[0] == '0' && var[1] == NUL))
     {
 	*array = NULL;
-	return TRUE;
+	return OK;
     }

     for (cp = var; *cp != NUL; ++cp)
@@ -43,8 +44,8 @@ tabstop_set(char_u *var, int **array)
 		if (cp != end)
 		    emsg(_(e_positive));
 		else
-		    emsg(_(e_invarg));
-		return FALSE;
+		    semsg(_(e_invarg2), cp);
+		return FAIL;
 	    }
 	}

@@ -55,26 +56,33 @@ tabstop_set(char_u *var, int **array)
 	    ++valcount;
 	    continue;
 	}
-	emsg(_(e_invarg));
-	return FALSE;
+	semsg(_(e_invarg2), var);
+	return FAIL;
     }

     *array = ALLOC_MULT(int, valcount + 1);
     if (*array == NULL)
-	return FALSE;
+	return FAIL;
     (*array)[0] = valcount;

     t = 1;
     for (cp = var; *cp != NUL;)
     {
-	(*array)[t++] = atoi((char *)cp);
-	while (*cp  != NUL && *cp != ',')
+	int n = atoi((char *)cp);
+
+	if (n < 0 || n > 9999)
+	{
+	    semsg(_(e_invarg2), cp);
+	    return FAIL;
+	}
+	(*array)[t++] = n;
+	while (*cp != NUL && *cp != ',')
 	    ++cp;
 	if (*cp != NUL)
 	    ++cp;
     }

-    return TRUE;
+    return OK;
 }

 /*
@@ -1591,7 +1599,7 @@ ex_retab(exarg_T *eap)

 #ifdef FEAT_VARTABS
     new_ts_str = eap->arg;
-    if (!tabstop_set(eap->arg, &new_vts_array))
+    if (tabstop_set(eap->arg, &new_vts_array) == FAIL)
 	return;
     while (vim_isdigit(*(eap->arg)) || *(eap->arg) == ',')
 	++(eap->arg);


Merge pull request #4707 from cyrusimap/lmtp_jmap_email_query_attachmentbody_sieve

lmtpd: support JMAP attachment body search in Sieve

@@ -61,7 +61,6 @@

 #include "carddav_db.h"
 #include "message.h"
-#include "xapian_wrap.h"

 struct email_contactfilter {
     const char *accountid;
@@ -124,13 +123,6 @@ extern void jmap_email_filtercondition_validate(const char *field, json_t *arg,
  *
  * Returns non-zero if filter matches.
  * On error, sets the JMAP error in err. */
-struct matchmime {
-    char *dbpath;
-    xapian_dbw_t *dbw;
-    message_t *m;
-    const struct buf *mime;
-    void *convmatch;
-};
 typedef struct matchmime matchmime_t;
 extern matchmime_t *jmap_email_matchmime_new(const struct buf *buf, json_t **err);
 extern void jmap_email_matchmime_free(matchmime_t **matchmimep);


Hash-collision denial-of-service vulnerabilities (#87)

* Add case insensitive SipHash implementation
* Replace ref hash function with SipHash
* Add label to link_ref struct.
* Update find_link_ref to compare link labels as well as hashes
* Update add_link_ref to disallow duplicate entries.
* cast to char from uint8_t for strncasecmp
* update README markdown, remove TODO
* add py2 wheel generation
* fix: add logic for older glibc not having getrandom, impacting staging

Co-authored-by: Nicolaas <nweidema@usc.edu>

@@ -0,0 +1,329 @@
+/*
+   SipHash reference C implementation
+
+   Copyright (c) 2012-2016 Jean-Philippe Aumasson
+   <jeanphilippe.aumasson@gmail.com>
+   Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
+   Copyright (c) 2017 Salvatore Sanfilippo <antirez@gmail.com>
+
+   To the extent possible under law, the author(s) have dedicated all copyright
+   and related and neighboring rights to this software to the public domain
+   worldwide. This software is distributed without any warranty.
+
+   You should have received a copy of the CC0 Public Domain Dedication along
+   with this software. If not, see
+   <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+   ----------------------------------------------------------------------------
+
+   This version was modified by Salvatore Sanfilippo <antirez@gmail.com>
+   in the following ways:
+
+   1. Hard-code 2-4 rounds in the hope the compiler can optimize it more
+      in this raw from. Anyway we always want the standard 2-4 variant.
+   2. Modify the prototype and implementation so that the function directly
+      returns an uint64_t value, the hash itself, instead of receiving an
+      output buffer. This also means that the output size is set to 8 bytes
+      and the 16 bytes output code handling was removed.
+   3. Provide a case insensitive variant to be used when hashing strings that
+      must be considered identical by the hash table regardless of the case.
+      If we don't have directly a case insensitive hash function, we need to
+      perform a text transformation in some temporary buffer, which is costly.
+   4. Remove debugging code.
+   5. Modified the original test.c file to be a stand-alone function testing
+      the function in the new form (returing an uint64_t) using just the
+      relevant test vector.
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
+
+#define U32TO8_LE(p, v)                                                        \
+    (p)[0] = (uint8_t)((v));                                                   \
+    (p)[1] = (uint8_t)((v) >> 8);                                              \
+    (p)[2] = (uint8_t)((v) >> 16);                                             \
+    (p)[3] = (uint8_t)((v) >> 24);
+
+#define U64TO8_LE(p, v)                                                        \
+    U32TO8_LE((p), (uint32_t)((v)));                                           \
+    U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+
+#define U8TO64_LE(p)                                                           \
+    (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) |                        \
+     ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) |                 \
+     ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) |                 \
+     ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
+
+#define U8TO64_LE_NOCASE(p)                                                    \
+    (((uint64_t)(tolower((p)[0]))) |                                           \
+     ((uint64_t)(tolower((p)[1])) << 8) |                                      \
+     ((uint64_t)(tolower((p)[2])) << 16) |                                     \
+     ((uint64_t)(tolower((p)[3])) << 24) |                                     \
+     ((uint64_t)(tolower((p)[4])) << 32) |                                              \
+     ((uint64_t)(tolower((p)[5])) << 40) |                                              \
+     ((uint64_t)(tolower((p)[6])) << 48) |                                              \
+     ((uint64_t)(tolower((p)[7])) << 56))
+
+#define SIPROUND                                                               \
+    do {                                                                       \
+        v0 += v1;                                                              \
+        v1 = ROTL(v1, 13);                                                     \
+        v1 ^= v0;                                                              \
+        v0 = ROTL(v0, 32);                                                     \
+        v2 += v3;                                                              \
+        v3 = ROTL(v3, 16);                                                     \
+        v3 ^= v2;                                                              \
+        v0 += v3;                                                              \
+        v3 = ROTL(v3, 21);                                                     \
+        v3 ^= v0;                                                              \
+        v2 += v1;                                                              \
+        v1 = ROTL(v1, 17);                                                     \
+        v1 ^= v2;                                                              \
+        v2 = ROTL(v2, 32);                                                     \
+    } while (0)
+
+uint64_t siphash(const uint8_t *in, const size_t inlen, const uint8_t *k) {
+    uint64_t hash;
+    uint8_t *out = (uint8_t*) &hash;
+    uint64_t v0 = 0x736f6d6570736575ULL;
+    uint64_t v1 = 0x646f72616e646f6dULL;
+    uint64_t v2 = 0x6c7967656e657261ULL;
+    uint64_t v3 = 0x7465646279746573ULL;
+    uint64_t k0 = U8TO64_LE(k);
+    uint64_t k1 = U8TO64_LE(k + 8);
+    uint64_t m;
+    const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
+    const int left = inlen & 7;
+    uint64_t b = ((uint64_t)inlen) << 56;
+    v3 ^= k1;
+    v2 ^= k0;
+    v1 ^= k1;
+    v0 ^= k0;
+
+    for (; in != end; in += 8) {
+        m = U8TO64_LE(in);
+        v3 ^= m;
+
+        SIPROUND;
+        SIPROUND;
+
+        v0 ^= m;
+    }
+
+    switch (left) {
+    case 7: b |= ((uint64_t)in[6]) << 48;
+    case 6: b |= ((uint64_t)in[5]) << 40;
+    case 5: b |= ((uint64_t)in[4]) << 32;
+    case 4: b |= ((uint64_t)in[3]) << 24;
+    case 3: b |= ((uint64_t)in[2]) << 16;
+    case 2: b |= ((uint64_t)in[1]) << 8;
+    case 1: b |= ((uint64_t)in[0]); break;
+    case 0: break;
+    }
+
+    v3 ^= b;
+
+    SIPROUND;
+    SIPROUND;
+
+    v0 ^= b;
+    v2 ^= 0xff;
+
+    SIPROUND;
+    SIPROUND;
+    SIPROUND;
+    SIPROUND;
+
+    b = v0 ^ v1 ^ v2 ^ v3;
+    U64TO8_LE(out, b);
+
+    return hash;
+}
+
+uint64_t siphash_nocase(const uint8_t *in, const size_t inlen, const uint8_t *k)
+{
+    uint64_t hash;
+    uint8_t *out = (uint8_t*) &hash;
+    uint64_t v0 = 0x736f6d6570736575ULL;
+    uint64_t v1 = 0x646f72616e646f6dULL;
+    uint64_t v2 = 0x6c7967656e657261ULL;
+    uint64_t v3 = 0x7465646279746573ULL;
+    uint64_t k0 = U8TO64_LE(k);
+    uint64_t k1 = U8TO64_LE(k + 8);
+    uint64_t m;
+    const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
+    const int left = inlen & 7;
+    uint64_t b = ((uint64_t)inlen) << 56;
+    v3 ^= k1;
+    v2 ^= k0;
+    v1 ^= k1;
+    v0 ^= k0;
+
+    for (; in != end; in += 8) {
+        m = U8TO64_LE_NOCASE(in);
+        v3 ^= m;
+
+        SIPROUND;
+        SIPROUND;
+
+        v0 ^= m;
+    }
+
+    switch (left) {
+    case 7: b |= ((uint64_t)tolower(in[6])) << 48;
+    case 6: b |= ((uint64_t)tolower(in[5])) << 40;
+    case 5: b |= ((uint64_t)tolower(in[4])) << 32;
+    case 4: b |= ((uint64_t)tolower(in[3])) << 24;
+    case 3: b |= ((uint64_t)tolower(in[2])) << 16;
+    case 2: b |= ((uint64_t)tolower(in[1])) << 8;
+    case 1: b |= ((uint64_t)tolower(in[0])); break;
+    case 0: break;
+    }
+
+    v3 ^= b;
+
+    SIPROUND;
+    SIPROUND;
+
+    v0 ^= b;
+    v2 ^= 0xff;
+
+    SIPROUND;
+    SIPROUND;
+    SIPROUND;
+    SIPROUND;
+
+    b = v0 ^ v1 ^ v2 ^ v3;
+    U64TO8_LE(out, b);
+
+    return hash;
+}
+
+
+/* --------------------------------- TEST ------------------------------------ */
+
+#ifdef SIPHASH_TEST
+
+const uint8_t vectors_sip64[64][8] = {
+    { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+    { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+    { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+    { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+    { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+    { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+    { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+    { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+    { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+    { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+    { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+    { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+    { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+    { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+    { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+    { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+    { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+    { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+    { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+    { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+    { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+    { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+    { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+    { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+    { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+    { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+    { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+    { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+    { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+    { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+    { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+    { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+    { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+    { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+    { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+    { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+    { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+    { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+    { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+    { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+    { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+    { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+    { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+    { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+    { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+    { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+    { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+    { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+    { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+    { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+    { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+    { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+    { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+    { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+    { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+    { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+    { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+    { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+    { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+    { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+    { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+    { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+    { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+    { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, },
+};
+
+
+/* Test siphash using a test vector. Returns 0 if the function passed
+ * all the tests, otherwise 1 is returned. */
+int siphash_test(void) {
+    uint8_t in[64], k[16];
+    int i;
+    int fails = 0;
+
+    for (i = 0; i < 16; ++i)
+        k[i] = i;
+
+    for (i = 0; i < 64; ++i) {
+        in[i] = i;
+        uint64_t hash = siphash(in, i, k);
+        const uint8_t *v = NULL;
+        v = (uint8_t *)vectors_sip64;
+        if (memcmp(&hash, v + (i * 8), 8)) {
+            /* printf("fail for %d bytes\n", i); */
+            fails++;
+        }
+    }
+
+    /* Run a few basic tests with the case insensitive version. */
+    uint64_t h1, h2;
+    h1 = siphash((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678");
+    h2 = siphash_nocase((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678");
+    if (h1 != h2) fails++;
+
+    h1 = siphash((uint8_t*)"hello world",11,(uint8_t*)"1234567812345678");
+    h2 = siphash_nocase((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678");
+    if (h1 != h2) fails++;
+
+    h1 = siphash((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678");
+    h2 = siphash_nocase((uint8_t*)"HELLO world",11,(uint8_t*)"1234567812345678");
+    if (h1 == h2) fails++;
+
+    if (!fails) return 0;
+    return 1;
+}
+
+int main(void) {
+    if (siphash_test() == 0) {
+        printf("SipHash test: OK\n");
+        return 0;
+    } else {
+        printf("SipHash test: FAILED\n");
+        return 1;
+    }
+}
+
+#endif
+