tag 851771 + patch
thanks

Hello,

TT-RSS is an important application for FreedomBox and it continues to
use php-gettext library. TT-RSS is currently not available for testing.
It would be nice to have it back.

To address this, I have implemented a parser for the plurals expressions
instead of using the eval() method as discussed in the upstream bug as
solution. This patch is under the same license as php-gettext (GPLv2 or
higher).

- A simple operator-precedence parser that prioritizes simplicity and
readability. Avoid using eval() for evaluating plural expressions.
  - Fixes CVE-2016-6175.
  - Fixes upstream bug https://bugs.launchpad.net/php-gettext/+bug/1606184
  - Fixes Debian bug https://bugs.debian.org/851771

- Grammar for parsing code is same as the grammar for GNU gettext
library:
http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/plural.y

- Extensive tests for various locales with help from Unicode's plurals
rules. Tests for invalid syntax and expression parsing.

This patch has been submitted upstream at
https://bugs.launchpad.net/php-gettext/+bug/1606184 . Please consider
applying the patch in Debian if the upstream doesn't do so shortly.

Thanks,

-- 
Sunil
From ebe92d9d97dc21b82225c6a7977adf87dd00f799 Mon Sep 17 00:00:00 2001
From: Sunil Mohan Adapa <su...@medhas.org>
Date: Thu, 11 Jun 2020 15:00:34 -0700
Subject: [PATCH] Iterate user table in a sorted way, fix tests with latest
 glib

This is primarily to help test cases which assume that the adopted algorithm
prioritizes the users in the exact reverse order they appear in the test
cases (and get inserted into the session in reverse order). With older glib
version, the five users being inserted happened to return the order expected by
the tests. With latest glib, due to a minor tweak in hashing strategy, the
insertion leads to unsorted list leading to failed tests.

In addition, GHashTable makes no guarantees about the stability of items when
iterating multiple times. Since the algorithm is sensitive to order of users, it
is best to return users in an order that is consistent over multiple calls and
stable over insert/remove operations.

This patch maintains a sorted list of user ids and uses it for iteration.

Closes: #22.

Signed-off-by: Sunil Mohan Adapa <su...@medhas.org>
---
 libinfinity/common/inf-user-table.c | 51 ++++++++++++++++-------------
 1 file changed, 28 insertions(+), 23 deletions(-)

diff --git a/libinfinity/common/inf-user-table.c b/libinfinity/common/inf-user-table.c
index 11b06b4..cb44ef5 100644
--- a/libinfinity/common/inf-user-table.c
+++ b/libinfinity/common/inf-user-table.c
@@ -36,15 +36,11 @@
  * users within the session.
  */
 
-typedef struct _InfUserTableForeachUserData InfUserTableForeachUserData;
-struct _InfUserTableForeachUserData {
-  InfUserTableForeachUserFunc func;
-  gpointer user_data;
-};
-
 typedef struct _InfUserTablePrivate InfUserTablePrivate;
 struct _InfUserTablePrivate {
   GHashTable* table;
+  /* To be able to iterate users in sorted order */
+  GSList* user_ids;
   /* TODO: It would be smarter to map the hash table to a helper struct
    * which stores the user availability, locality and the InfUser object */
   GSList* availables;
@@ -179,15 +175,11 @@ inf_user_table_lookup_user_by_name_func(gpointer key,
   return FALSE;
 }
 
-static void
-inf_user_table_foreach_user_func(gpointer key,
-                                 gpointer value,
-                                 gpointer user_data)
+static gint
+inf_user_ids_list_sort_compare_func(gconstpointer a,
+                                    gconstpointer b)
 {
-  InfUserTableForeachUserData* data;
-  data = (InfUserTableForeachUserData*)user_data;
-
-  data->func(INF_USER(value), data->user_data);
+  return GPOINTER_TO_UINT(a) - GPOINTER_TO_UINT(b);
 }
 
 static void
@@ -197,6 +189,7 @@ inf_user_table_init(InfUserTable* user_table)
   priv = INF_USER_TABLE_PRIVATE(user_table);
 
   priv->table = g_hash_table_new_full(NULL, NULL, NULL, NULL);
+  priv->user_ids = NULL;
   priv->availables = NULL;
   priv->locals = NULL;
 }
@@ -216,6 +209,9 @@ inf_user_table_dispose(GObject* object)
   g_slist_free(priv->availables);
   priv->availables = NULL;
 
+  g_slist_free(priv->user_ids);
+  priv->user_ids = NULL;
+
   g_hash_table_foreach(
     priv->table,
     inf_user_table_dispose_foreach_func,
@@ -256,6 +252,12 @@ inf_user_table_add_user_handler(InfUserTable* user_table,
   g_hash_table_insert(priv->table, GUINT_TO_POINTER(id), user);
   g_object_ref(user);
 
+  priv->user_ids = g_slist_insert_sorted(
+    priv->user_ids,
+    GUINT_TO_POINTER(id),
+    inf_user_ids_list_sort_compare_func
+  );
+
   g_signal_connect(
     G_OBJECT(user),
     "notify::status",
@@ -314,6 +316,8 @@ inf_user_table_remove_user_handler(InfUserTable* user_table,
     );
   }
 
+  priv->user_ids = g_slist_remove(priv->user_ids, GUINT_TO_POINTER(id));
+
   inf_user_table_unref_user(user_table, user);
   g_assert(g_hash_table_lookup(priv->table, GUINT_TO_POINTER(id)) == user);
   g_hash_table_remove(priv->table, GUINT_TO_POINTER(id));
@@ -646,21 +650,22 @@ inf_user_table_foreach_user(InfUserTable* user_table,
                             gpointer user_data)
 {
   InfUserTablePrivate* priv;
-  InfUserTableForeachUserData data;
+  InfUser* user;
+  GSList* item;
+
+  guint user_id;
 
   g_return_if_fail(INF_IS_USER_TABLE(user_table));
   g_return_if_fail(func != NULL);
 
   priv = INF_USER_TABLE_PRIVATE(user_table);
 
-  data.func = func;
-  data.user_data = user_data;
-
-  g_hash_table_foreach(
-    priv->table,
-    inf_user_table_foreach_user_func,
-    &data
-  );
+  for(item = priv->user_ids; item != NULL; item = g_slist_next(item))
+  {
+    user_id = GPOINTER_TO_UINT(item->data);
+    user = inf_user_table_lookup_user_by_id(user_table, user_id);
+    func(user, user_data);
+  }
 }
 
 /**
-- 
2.20.1

From 4fe6f4b00e98a680fb16e8f68c081edfcaea3cdc Mon Sep 17 00:00:00 2001
From: Sunil Mohan Adapa <su...@medhas.org>
Date: Thu, 11 Jun 2020 13:11:52 -0700
Subject: [PATCH] Iterate user table in a sorted way, fix tests with latest
 glib

This is primarily to help test cases which assume that the adopted algorithm
prioritizes the users in the exact reverse order they appear in the test
cases (and get inserted into the session in reverse order). With older glib
version, the five users being inserted happened to return the order expected by
the tests. With latest glib, due to a minor tweak in hashing strategy, the
insertion leads to unsorted list leading to failed tests.

In addition, GHashTable makes no guarantees about the stability of items when
iterating multiple times. Since the algorithm is sensitive to order of users, it
is best to return users in an order that is consistent over multiple calls and
stable over insert/remove operations.

This patch sorts the keys during iteration of users in the user table.

Closes: #22.

Signed-off-by: Sunil Mohan Adapa <su...@medhas.org>
---
 libinfinity/common/inf-user-table.c | 42 ++++++++++++++---------------
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/libinfinity/common/inf-user-table.c b/libinfinity/common/inf-user-table.c
index 11b06b4..eecc72e 100644
--- a/libinfinity/common/inf-user-table.c
+++ b/libinfinity/common/inf-user-table.c
@@ -36,12 +36,6 @@
  * users within the session.
  */
 
-typedef struct _InfUserTableForeachUserData InfUserTableForeachUserData;
-struct _InfUserTableForeachUserData {
-  InfUserTableForeachUserFunc func;
-  gpointer user_data;
-};
-
 typedef struct _InfUserTablePrivate InfUserTablePrivate;
 struct _InfUserTablePrivate {
   GHashTable* table;
@@ -179,15 +173,11 @@ inf_user_table_lookup_user_by_name_func(gpointer key,
   return FALSE;
 }
 
-static void
-inf_user_table_foreach_user_func(gpointer key,
-                                 gpointer value,
-                                 gpointer user_data)
+static gint
+inf_user_ids_list_sort_compare_func(gconstpointer a,
+                                    gconstpointer b)
 {
-  InfUserTableForeachUserData* data;
-  data = (InfUserTableForeachUserData*)user_data;
-
-  data->func(INF_USER(value), data->user_data);
+  return GPOINTER_TO_UINT(a) - GPOINTER_TO_UINT(b);
 }
 
 static void
@@ -646,21 +636,29 @@ inf_user_table_foreach_user(InfUserTable* user_table,
                             gpointer user_data)
 {
   InfUserTablePrivate* priv;
-  InfUserTableForeachUserData data;
+  GList* user_ids_list;
+  GList* item;
+  InfUser* user;
+
+  guint user_id;
 
   g_return_if_fail(INF_IS_USER_TABLE(user_table));
   g_return_if_fail(func != NULL);
 
   priv = INF_USER_TABLE_PRIVATE(user_table);
 
-  data.func = func;
-  data.user_data = user_data;
-
-  g_hash_table_foreach(
-    priv->table,
-    inf_user_table_foreach_user_func,
-    &data
+  user_ids_list = g_hash_table_get_keys(priv->table);
+  user_ids_list = g_list_sort(
+    user_ids_list,
+    inf_user_ids_list_sort_compare_func
   );
+  for(item = user_ids_list; item != NULL; item = g_list_next(item))
+  {
+    user_id = GPOINTER_TO_UINT(item->data);
+    user = inf_user_table_lookup_user_by_id(user_table, user_id);
+    func(user, user_data);
+  }
+  g_list_free(user_ids_list);
 }
 
 /**
-- 
2.20.1

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to