<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40196 >

On 07/04/2008, Pepeto _ wrote:
>
>  Try with this patch.

 Bugs I reported cannot be reproduced when this patch is applied.
Still, I don't think patch is correct. At  the very least changes you
make should not be required (if other parts of the code work
correctly), and I'm not entirely sure that they themselves never act
as bug.

 Note that if *str0 != '\0' (so it will pass the test) and *str1 ==
'\0' (which you are testing), they are not equal (later test).

>  I also noticed a long time ago that the client sends lot of wrong
>  commands to the server, confusing player names and connection names, the
>  commands names and adding '"' characters that the server doesn't remove
>  when it interpret it. See PR#39614.

 Actually, it's not client bug that it sends quoted command
parameters. It's server bug that they are not handled correctly.
Inspecting all these issues indeed end to same core bug; length is not
handled correctly for quoted string. match_prefix() considers quoted
and non-quoted strings different because their length, and sometimes
does not compare enough characters: (Comparing """""" and cazfi are
sometimes considered exact match as there's five characters to match
in cazfi, and five first characters of """"" are to be ignored)

 Instead of adding minimal fix (which would be ugly hack) to existing
system, attached patch makes soem overall changes to quoted string
matching. To me, this new behavior seems much more sensible than old
one.

 - Only strings both starting and ending with '"' are considered
quoted and these starting and ending quotes are only ones ignored
during matching
 - Correct string length comparison for quoted strings implemented and used


 Remaining minor issue is that server messages display parameters as
they were originally given.

/aitoggle cazfi -> /aitoggle: No player by the name of 'cazfi'.
/aitoggle "cazfi" -> /aitoggle: No player by the name of '"cazfi"'.


 - ML

diff -Nurd -X.diff_ignore freeciv/common/connection.c freeciv/common/connection.c
--- freeciv/common/connection.c	2008-03-08 16:32:49.000000000 +0200
+++ freeciv/common/connection.c	2008-04-08 17:21:10.000000000 +0300
@@ -440,7 +440,8 @@
 
   *result = match_prefix(connection_accessor,
 			 conn_list_size(game.all_connections),
-			 MAX_LEN_NAME-1, mystrncasecmp, user_name, &ind);
+			 MAX_LEN_NAME-1, mystrncasecmp, NULL,
+                         user_name, &ind);
   
   if (*result < M_PRE_AMBIGUOUS) {
     return conn_list_get(game.all_connections, ind);
diff -Nurd -X.diff_ignore freeciv/common/player.c freeciv/common/player.c
--- freeciv/common/player.c	2008-03-08 16:32:49.000000000 +0200
+++ freeciv/common/player.c	2008-04-08 17:22:42.000000000 +0300
@@ -396,7 +396,8 @@
   int ind;
 
   *result = match_prefix(player_name_by_number, game.info.nplayers,
-			 MAX_LEN_NAME-1, mystrncasequotecmp, name, &ind);
+			 MAX_LEN_NAME-1, mystrncasequotecmp,
+                         effectivestrlenquote, name, &ind);
 
   if (*result < M_PRE_AMBIGUOUS) {
     return player_by_number(ind);
diff -Nurd -X.diff_ignore freeciv/server/stdinhand.c freeciv/server/stdinhand.c
--- freeciv/server/stdinhand.c	2008-04-06 11:24:53.000000000 +0300
+++ freeciv/server/stdinhand.c	2008-04-08 17:26:51.000000000 +0300
@@ -173,7 +173,7 @@
   int ind;
 
   result = match_prefix(command_name_by_number, CMD_NUM, 0,
-			mystrncasecmp, token, &ind);
+			mystrncasecmp, NULL, token, &ind);
 
   if (result < M_PRE_AMBIGUOUS) {
     return ind;
@@ -1486,7 +1486,7 @@
   }
 
   result = match_prefix(optname_accessor, SETTINGS_NUM, 0, mystrncasecmp,
-			name, &ind);
+			NULL, name, &ind);
 
   return ((result < M_PRE_AMBIGUOUS) ? ind :
 	  (result == M_PRE_AMBIGUOUS) ? -2 : -1);
@@ -4008,7 +4008,7 @@
     /* no commands means no help, either */
 
   match_result = match_prefix(helparg_accessor, HELP_ARG_NUM, 0,
-			      mystrncasecmp, arg, &ind);
+			      mystrncasecmp, NULL, arg, &ind);
 
   if (match_result==M_PRE_EMPTY) {
     show_help_intro(caller, CMD_HELP);
@@ -4082,7 +4082,7 @@
 
   remove_leading_trailing_spaces(arg);
   match_result = match_prefix(listarg_accessor, LIST_ARG_NUM, 0,
-			      mystrncasecmp, arg, &ind_int);
+			      mystrncasecmp, NULL, arg, &ind_int);
   ind = ind_int;
 
   if (match_result > M_PRE_EMPTY) {
diff -Nurd -X.diff_ignore freeciv/utility/shared.c freeciv/utility/shared.c
--- freeciv/utility/shared.c	2008-03-11 11:27:15.000000000 +0200
+++ freeciv/utility/shared.c	2008-04-08 17:19:54.000000000 +0300
@@ -1485,12 +1485,17 @@
 			       size_t n_names,
 			       size_t max_len_name,
 			       m_pre_strncmp_fn_t cmp_fn,
+                               m_strlen_fn_t len_fn,
 			       const char *prefix,
 			       int *ind_result)
 {
   int i, len, nmatches;
 
-  len = strlen(prefix);
+  if (len_fn == NULL) {
+    len = strlen(prefix);
+  } else {
+    len = len_fn(prefix);
+  }
   if (len == 0) {
     return M_PRE_EMPTY;
   }
diff -Nurd -X.diff_ignore freeciv/utility/shared.h freeciv/utility/shared.h
--- freeciv/utility/shared.h	2008-03-08 16:32:11.000000000 +0200
+++ freeciv/utility/shared.h	2008-04-08 17:21:57.000000000 +0300
@@ -224,10 +224,14 @@
 /* function type to compare prefix: */
 typedef int (*m_pre_strncmp_fn_t)(const char *, const char *, size_t n);
 
+/* function type to calculate effective string length: */
+typedef size_t (m_strlen_fn_t)(const char *str);
+
 enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn,
 			       size_t n_names,
 			       size_t max_len_name,
 			       m_pre_strncmp_fn_t cmp_fn,
+                               m_strlen_fn_t len_fn,
 			       const char *prefix,
 			       int *ind_result);
 
diff -Nurd -X.diff_ignore freeciv/utility/support.c freeciv/utility/support.c
--- freeciv/utility/support.c	2008-01-31 01:26:00.000000000 +0200
+++ freeciv/utility/support.c	2008-04-08 22:46:24.000000000 +0300
@@ -135,24 +135,66 @@
 }
 
 /***************************************************************
-  Compare strings like strncasecmp() but ignoring quotes in
-  either string. Quotes still count towards n.
+  Count length of string without possible surrounding quotes.
+***************************************************************/
+size_t effectivestrlenquote(const char *str)
+{
+  int len = strlen(str);
+
+  if (str[0] == '"' && str[len-1] == '"') {
+    return len - 2;
+  }
+
+  return len;
+}
+
+/***************************************************************
+  Compare strings like strncasecmp() but ignoring surrounding
+  quotes in either string.
 ***************************************************************/
 int mystrncasequotecmp(const char *str0, const char *str1, size_t n)
 {
   size_t i;
-  char c;
+  size_t len0 = strlen(str0); /* TODO: We iterate string once already here, */
+  size_t len1 = strlen(str1); /*       could iterate only once */
+  size_t cmplen;
 
-  for (i = 0; i < n && *str0 != '\0'; i++) {
-    if (my_tolower(*str0) != my_tolower(*str1)
-        && *str0 != '"' && *str1 != '"') {
+  if (str0[0] == '"') {
+    if (str0[len0 - 1] == '"') {
+      /* Surrounded with quotes */
+      str0++;
+      len0 -= 2;
+    }
+  }
+
+  if (str1[0] == '"') {
+    if (str1[len1 - 1] == '"') {
+      /* Surrounded with quotes */
+      str1++;
+      len1 -= 2;
+    }
+  }
+
+  if (len0 < n || len1 < n) {
+    /* One of the strings is shorter than what should be compared... */
+    if (len0 != len1) {
+      /* ...and another is longer than it. */
+      return len0 - len1;
+    }
+
+    cmplen = len0; /* This avoids comparing ending quote */
+  } else {
+    cmplen = n;
+  }
+
+  for (i = 0; i < cmplen ; i++, str0++, str1++) {
+    if (my_tolower(*str0) != my_tolower(*str1)) {
       return ((int) (unsigned char) my_tolower(*str0))
              - ((int) (unsigned char) my_tolower(*str1));
     }
-    c = *str0;
-    str0 += (*str1 != '"');
-    str1 += (c != '"');
   }
+
+  /* All characters compared and all matched */
   return 0;
 }
 
diff -Nurd -X.diff_ignore freeciv/utility/support.h freeciv/utility/support.h
--- freeciv/utility/support.h	2008-01-15 04:53:30.000000000 +0200
+++ freeciv/utility/support.h	2008-04-08 17:22:18.000000000 +0300
@@ -74,6 +74,8 @@
 int mystrncasecmp(const char *str0, const char *str1, size_t n);
 int mystrncasequotecmp(const char *str0, const char *str1, size_t n);
 
+size_t effectivestrlenquote(const char *str);
+
 char *mystrcasestr(const char *haystack, const char *needle);
 
 const char *mystrerror(void);
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to