git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH/RFD] fix connection via git protocol

From
Jeff King <peff@peff.net>
Date
Apr 18, 2023, 03:39 UTC
Message-ID
<20230418033904.GA60552@coredump.intra.peff.net>
In-Reply-To
<xmqq1qkio4cq.fsf@gitster.g>
On Mon, Apr 17, 2023 at 09:33:57AM -0700, Junio C Hamano wrote:
Show 19 quoted lines
> > diff --git a/connect.c b/connect.c
> > index fd3179e545..1eba71e34c 100644
> > --- a/connect.c
> > +++ b/connect.c
> > @@ -753,7 +753,7 @@ static char *host_end(char **hoststart, int removebrackets)
> >  }
> >  
> >  #define STR_(s)	# s
> > -#define STR(s)	STR_(s)
> > +#define STR(s) (STR_(s) + BUILD_ASSERT_OR_ZERO(s))
> 
> OOoooh.  Clever.  A pointer plus N indexes into an array, but if the
> offset is N then the pointer is left intact so the caller does not
> see the difference.
> 
> > ... But the
> > BUILD_ASSERT doesn't seem too bad to me.
> 
> Indeed.

So I started to write this up as a patch, but there's another subtle thing going on.

The BUILD_ASSERT is actually checking two things: that the result compiles (which is what we care about here), and that the expression it evaluates is nonzero (which we don't).

So this would fail for example with:
  #define ZERO 0
  const char *x = STR(ZERO);

That is OK for our purposes here (a zero port does not make any sense). But it feels a bit weird for a macro as generically named as STR(). At least it's local to the one file. But maybe it should be PORT_TO_STR() or something.

All of that makes me wonder if we wouldn't be just as happy with it as a string in the first place. In three out of four locations that use it, they want the string anyway (to feed to getaddrinfo). And in the final one (git-daemon), we need to convert from the user's "--port" anyway, so there's always some string-to-int parsing. And depending on the #ifdefs, in most cases we turn it back into a string anyway to feed to...you guessed it, getaddrinfo!

The exception is when NO_IPV6 is defined, in which we do want the numeric value. But we could delay parsing until that point (and otherwise let getaddrinfo handle, which seems more correct anyway).

Something like this (though I'd probably split it into a few patches to reason about the motivation and implications of each):

diff --git a/cache.h b/cache.h
index 2f21704da9..2ece09a2b8 100644
--- a/cache.h
+++ b/cache.h
@@ -58,7 +58,7 @@
  *
  * See http://www.iana.org/assignments/port-numbers
  */
-#define DEFAULT_GIT_PORT 9418
+#define DEFAULT_GIT_PORT "9418"
 
 /*
  * Basic data structures for the directory cache
diff --git a/connect.c b/connect.c
index fd3179e545..189367604c 100644
--- a/connect.c
+++ b/connect.c
@@ -1,4 +1,5 @@
 #include "git-compat-util.h"
+#include "cache.h" /* or protocol.h after Elijah's patch */
 #include "config.h"
 #include "environment.h"
 #include "gettext.h"
@@ -752,9 +753,6 @@ static char *host_end(char **hoststart, int removebrackets)
 	return end;
 }
 
-#define STR_(s)	# s
-#define STR(s)	STR_(s)
-
 static void get_host_and_port(char **host, const char **port)
 {
 	char *colon, *end;
@@ -798,7 +796,7 @@ static int git_tcp_connect_sock(char *host, int flags)
 {
 	struct strbuf error_message = STRBUF_INIT;
 	int sockfd = -1;
-	const char *port = STR(DEFAULT_GIT_PORT);
+	const char *port = DEFAULT_GIT_PORT;
 	struct addrinfo hints, *ai0, *ai;
 	int gai;
 	int cnt = 0;
@@ -868,7 +866,7 @@ static int git_tcp_connect_sock(char *host, int flags)
 {
 	struct strbuf error_message = STRBUF_INIT;
 	int sockfd = -1;
-	const char *port = STR(DEFAULT_GIT_PORT);
+	const char *port = DEFAULT_GIT_PORT;
 	char *ep;
 	struct hostent *he;
 	struct sockaddr_in sa;
@@ -1020,7 +1018,7 @@ static int git_use_proxy(const char *host)
 
 static struct child_process *git_proxy_connect(int fd[2], char *host)
 {
-	const char *port = STR(DEFAULT_GIT_PORT);
+	const char *port = DEFAULT_GIT_PORT;
 	struct child_process *proxy;
 
 	get_host_and_port(&host, &port);
diff --git a/daemon.c b/daemon.c
index db8a31a6ea..ce692bad35 100644
--- a/daemon.c
+++ b/daemon.c
@@ -984,22 +984,20 @@ static const char *ip2str(int family, struct sockaddr *sin, socklen_t len)
 
 #ifndef NO_IPV6
 
-static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist)
+static int setup_named_sock(char *listen_addr, const char *listen_port, struct socketlist *socklist)
 {
 	int socknum = 0;
-	char pbuf[NI_MAXSERV];
 	struct addrinfo hints, *ai0, *ai;
 	int gai;
 	long flags;
 
-	xsnprintf(pbuf, sizeof(pbuf), "%d", listen_port);
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family = AF_UNSPEC;
 	hints.ai_socktype = SOCK_STREAM;
 	hints.ai_protocol = IPPROTO_TCP;
 	hints.ai_flags = AI_PASSIVE;
 
-	gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
+	gai = getaddrinfo(listen_addr, listen_port, &hints, &ai0);
 	if (gai) {
 		logerror("getaddrinfo() for %s failed: %s", listen_addr, gai_strerror(gai));
 		return 0;
@@ -1065,15 +1063,27 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
 
 #else /* NO_IPV6 */
 
-static int setup_named_sock(char *listen_addr, int listen_port, struct socketlist *socklist)
+static int parse_port(const char *s)
+{
+	unsigned long ret;
+	char *end;
+
+	ret = strtoul(s, &end, 0);
+	if (!ret || ret > 65535 || *end)
+		die(_("invalid listen port: %s"), s);
+
+	return ret;
+}
+
+static int setup_named_sock(char *listen_addr, const char *listen_port, struct socketlist *socklist)
 {
 	struct sockaddr_in sin;
 	int sockfd;
 	long flags;
 
 	memset(&sin, 0, sizeof sin);
 	sin.sin_family = AF_INET;
-	sin.sin_port = htons(listen_port);
+	sin.sin_port = parse_port(listen_port);
 
 	if (listen_addr) {
 		/* Well, host better be an IP address here. */
@@ -1122,7 +1132,7 @@ static int setup_named_sock(char *listen_addr, int listen_port, struct socketlis
 
 #endif
 
-static void socksetup(struct string_list *listen_addr, int listen_port, struct socketlist *socklist)
+static void socksetup(struct string_list *listen_addr, const char *listen_port, struct socketlist *socklist)
 {
 	if (!listen_addr->nr)
 		setup_named_sock(NULL, listen_port, socklist);
@@ -1133,7 +1143,7 @@ static void socksetup(struct string_list *listen_addr, int listen_port, struct s
 						   listen_port, socklist);
 
 			if (socknum == 0)
-				logerror("unable to allocate any listen sockets for host %s on port %u",
+				logerror("unable to allocate any listen sockets for host %s on port %s",
 					 listen_addr->items[i].string, listen_port);
 		}
 	}
@@ -1246,14 +1256,14 @@ static struct credentials *prepare_credentials(const char *user_name,
 }
 #endif
 
-static int serve(struct string_list *listen_addr, int listen_port,
+static int serve(struct string_list *listen_addr, const char *listen_port,
     struct credentials *cred)
 {
 	struct socketlist socklist = { NULL, 0, 0 };
 
 	socksetup(listen_addr, listen_port, &socklist);
 	if (socklist.nr == 0)
-		die("unable to allocate any listen sockets on port %u",
+		die("unable to allocate any listen sockets on port %s",
 		    listen_port);
 
 	drop_privileges(cred);
@@ -1265,7 +1275,7 @@ static int serve(struct string_list *listen_addr, int listen_port,
 
 int cmd_main(int argc, const char **argv)
 {
-	int listen_port = 0;
+	const char *listen_port = NULL;
 	struct string_list listen_addr = STRING_LIST_INIT_NODUP;
 	int serve_mode = 0, inetd_mode = 0;
 	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
@@ -1282,13 +1292,8 @@ int cmd_main(int argc, const char **argv)
 			continue;
 		}
 		if (skip_prefix(arg, "--port=", &v)) {
-			char *end;
-			unsigned long n;
-			n = strtoul(v, &end, 0);
-			if (*v && !*end) {
-				listen_port = n;
-				continue;
-			}
+			listen_port = v;
+			continue;
 		}
 		if (!strcmp(arg, "--serve")) {
 			serve_mode = 1;
@@ -1439,7 +1444,7 @@ int cmd_main(int argc, const char **argv)
 
 	if (inetd_mode && (listen_port || (listen_addr.nr > 0)))
 		die("--listen= and --port= are incompatible with --inetd");
-	else if (listen_port == 0)
+	else if (!listen_port)
 		listen_port = DEFAULT_GIT_PORT;
 
 	if (group_name && !user_name)
Previous: Junio C HamanoNext: Junio C Hamano
Message 74 of 101 in “Header cleanups (splitting up cache.h)”
  1. 00/24 Header cleanups (splitting up cache.h)Elijah Newren via GitGitGadget, Apr 1, 2023
  2. 03/24 treewide: be explicit about dependence on convert.hElijah Newren via GitGitGadget, Apr 1, 2023
  3. 01/24 treewide: be explicit about dependence on trace.h & trace2.hElijah Newren via GitGitGadget, Apr 1, 2023
  4. 02/24 treewide: be explicit about dependence on advice.hElijah Newren via GitGitGadget, Apr 1, 2023
  5. 04/24 treewide: be explicit about dependence on pack-revindex.hElijah Newren via GitGitGadget, Apr 1, 2023
  6. 05/24 treewide: be explicit about dependence on oid-array.hElijah Newren via GitGitGadget, Apr 1, 2023
  7. 06/24 treewide: be explicit about dependence on mem-pool.hElijah Newren via GitGitGadget, Apr 1, 2023
  8. 10/24 git-zlib: move declarations for git-zlib functions from cache.hElijah Newren via GitGitGadget, Apr 1, 2023
  9. 07/24 treewide: remove unnecessary cache.h inclusionElijah Newren via GitGitGadget, Apr 1, 2023
  10. 09/24 treewide: remove cache.h inclusion due to object-name.h changesElijah Newren via GitGitGadget, Apr 1, 2023
  11. 11/24 treewide: remove cache.h inclusion due to git-zlib changesElijah Newren via GitGitGadget, Apr 1, 2023
  12. 13/24 treewide: remove cache.h inclusion due to object-file.h changesElijah Newren via GitGitGadget, Apr 1, 2023
  13. 08/24 object-name.h: move declarations for object-name.c functions from cache.hElijah Newren via GitGitGadget, Apr 1, 2023
  14. 14/24 object.h: move an inline function and some defines from cache.hElijah Newren via GitGitGadget, Apr 1, 2023
  15. 17/24 pager.h: move declarations for pager.c functions from cache.hElijah Newren via GitGitGadget, Apr 1, 2023
  16. 12/24 object-file.h: move declarations for object-file.c functions from cache.hElijah Newren via GitGitGadget, Apr 1, 2023
  17. 16/24 treewide: remove cache.h inclusion due to editor.h changesElijah Newren via GitGitGadget, Apr 1, 2023
  18. 20/24 strbuf: move forward declarations to beginning of fileElijah Newren via GitGitGadget, Apr 1, 2023
  19. 19/24 cache.h: remove unnecessary includesElijah Newren via GitGitGadget, Apr 1, 2023
  20. 15/24 editor: move editor-related functions and declarations into common fileElijah Newren via GitGitGadget, Apr 1, 2023
  21. 23/24 chdir-notify, quote: replace cache.h include with path.hElijah Newren via GitGitGadget, Apr 1, 2023
  22. 22/24 treewide: reduce includes of cache.h in other headersElijah Newren via GitGitGadget, Apr 1, 2023
  23. 21/24 treewide: remove double forward declaration of read_in_fullElijah Newren via GitGitGadget, Apr 1, 2023
  24. 18/24 treewide: remove cache.h inclusion due to pager.h changesElijah Newren via GitGitGadget, Apr 1, 2023
  25. 24/24 mailmap, quote: move declarations of global vars to correct unitElijah Newren via GitGitGadget, Apr 1, 2023
  26. Elijah NewrenApr 3, 2023
  27. 00/24 Header cleanups (splitting up cache.h)Elijah Newren via GitGitGadget, Apr 4, 2023
  28. 01/24 treewide: be explicit about dependence on trace.h & trace2.hElijah Newren via GitGitGadget, Apr 4, 2023
  29. 04/24 treewide: be explicit about dependence on pack-revindex.hElijah Newren via GitGitGadget, Apr 4, 2023
  30. 05/24 treewide: be explicit about dependence on oid-array.hElijah Newren via GitGitGadget, Apr 4, 2023
  31. 03/24 treewide: be explicit about dependence on convert.hElijah Newren via GitGitGadget, Apr 4, 2023
  32. 06/24 treewide: be explicit about dependence on mem-pool.hElijah Newren via GitGitGadget, Apr 4, 2023
  33. 02/24 treewide: be explicit about dependence on advice.hElijah Newren via GitGitGadget, Apr 4, 2023
  34. 07/24 treewide: remove unnecessary cache.h inclusionElijah Newren via GitGitGadget, Apr 4, 2023
  35. 11/24 treewide: remove cache.h inclusion due to git-zlib changesElijah Newren via GitGitGadget, Apr 4, 2023
  36. 10/24 git-zlib: move declarations for git-zlib functions from cache.hElijah Newren via GitGitGadget, Apr 4, 2023
  37. 09/24 treewide: remove cache.h inclusion due to object-name.h changesElijah Newren via GitGitGadget, Apr 4, 2023
  38. 08/24 object-name.h: move declarations for object-name.c functions from cache.hElijah Newren via GitGitGadget, Apr 4, 2023
  39. 13/24 treewide: remove cache.h inclusion due to object-file.h changesElijah Newren via GitGitGadget, Apr 4, 2023
  40. 17/24 treewide: remove cache.h inclusion due to editor.h changesElijah Newren via GitGitGadget, Apr 4, 2023
  41. 14/24 object.h: move some inline functions and defines from cache.hElijah Newren via GitGitGadget, Apr 4, 2023
  42. 12/24 object-file.h: move declarations for object-file.c functions from cache.hElijah Newren via GitGitGadget, Apr 4, 2023
  43. 15/24 treewide: remove cache.h inclusion due to object.h changesElijah Newren via GitGitGadget, Apr 4, 2023
  44. 16/24 editor: move editor-related functions and declarations into common fileElijah Newren via GitGitGadget, Apr 4, 2023
  45. 20/24 cache.h: remove unnecessary includesElijah Newren via GitGitGadget, Apr 4, 2023
  46. 18/24 pager.h: move declarations for pager.c functions from cache.hElijah Newren via GitGitGadget, Apr 4, 2023
  47. 19/24 treewide: remove cache.h inclusion due to pager.h changesElijah Newren via GitGitGadget, Apr 4, 2023
  48. 22/24 treewide: remove double forward declaration of read_in_fullElijah Newren via GitGitGadget, Apr 4, 2023
  49. 21/24 strbuf: move forward declarations to beginning of fileElijah Newren via GitGitGadget, Apr 4, 2023
  50. Calvin WanApr 5, 2023
  51. Elijah NewrenApr 7, 2023
  52. Calvin WanApr 10, 2023
  53. Elijah NewrenApr 10, 2023
  54. 24/24 mailmap, quote: move declarations of global vars to correct unitElijah Newren via GitGitGadget, Apr 4, 2023
  55. 23/24 treewide: reduce includes of cache.h in other headersElijah Newren via GitGitGadget, Apr 4, 2023
  56. Calvin WanApr 5, 2023
  57. Elijah NewrenApr 7, 2023
  58. Calvin WanApr 10, 2023
  59. 00/23 Header cleanups (splitting up cache.h)Elijah Newren via GitGitGadget, Apr 11, 2023
  60. 02/23 treewide: be explicit about dependence on advice.hElijah Newren via GitGitGadget, Apr 11, 2023
  61. 03/23 treewide: be explicit about dependence on convert.hElijah Newren via GitGitGadget, Apr 11, 2023
  62. 01/23 treewide: be explicit about dependence on trace.h & trace2.hElijah Newren via GitGitGadget, Apr 11, 2023
  63. 04/23 treewide: be explicit about dependence on pack-revindex.hElijah Newren via GitGitGadget, Apr 11, 2023
  64. 05/23 treewide: be explicit about dependence on oid-array.hElijah Newren via GitGitGadget, Apr 11, 2023
  65. 06/23 treewide: be explicit about dependence on mem-pool.hElijah Newren, Apr 11, 2023
  66. 07/23 treewide: remove unnecessary cache.h inclusionElijah Newren, Apr 11, 2023
  67. fix connection via git protocolMichael J Gruber, Apr 15, 2023
  68. Elijah NewrenApr 16, 2023
  69. Elijah NewrenApr 16, 2023
  70. Michael J GruberApr 16, 2023
  71. Jeff KingApr 17, 2023
  72. Junio C HamanoApr 17, 2023
  73. Junio C HamanoApr 17, 2023
  74. Jeff KingApr 18, 2023
  75. Junio C HamanoApr 18, 2023
  76. Elijah NewrenApr 18, 2023
  77. Jeff KingApr 18, 2023
  78. Junio C HamanoApr 17, 2023
  79. Elijah NewrenApr 18, 2023
  80. Junio C HamanoApr 18, 2023
  81. Eric SunshineApr 18, 2023
  82. Elijah NewrenApr 19, 2023
  83. Junio C HamanoApr 24, 2023
  84. Elijah NewrenApr 19, 2023
  85. 09/23 treewide: remove cache.h inclusion due to object-name.h changesElijah Newren, Apr 11, 2023
  86. 10/23 git-zlib: move declarations for git-zlib functions from cache.hElijah Newren, Apr 11, 2023
  87. 08/23 object-name.h: move declarations for object-name.c functions from cache.hElijah Newren, Apr 11, 2023
  88. 11/23 treewide: remove cache.h inclusion due to git-zlib changesElijah Newren, Apr 11, 2023
  89. 13/23 treewide: remove cache.h inclusion due to object-file.h changesElijah Newren, Apr 11, 2023
  90. 12/23 object-file.h: move declarations for object-file.c functions from cache.hElijah Newren, Apr 11, 2023
  91. 14/23 object.h: move some inline functions and defines from cache.hElijah Newren, Apr 11, 2023
  92. 15/23 treewide: remove cache.h inclusion due to object.h changesElijah Newren, Apr 11, 2023
  93. 16/23 editor: move editor-related functions and declarations into common fileElijah Newren, Apr 11, 2023
  94. 17/23 treewide: remove cache.h inclusion due to editor.h changesElijah Newren, Apr 11, 2023
  95. 18/23 pager.h: move declarations for pager.c functions from cache.hElijah Newren, Apr 11, 2023
  96. 19/23 treewide: remove cache.h inclusion due to pager.h changesElijah Newren, Apr 11, 2023
  97. 20/23 cache.h: remove unnecessary includesElijah Newren, Apr 11, 2023
  98. 21/23 treewide: remove double forward declaration of read_in_fullElijah Newren, Apr 11, 2023
  99. 22/23 treewide: reduce includes of cache.h in other headersElijah Newren, Apr 11, 2023
  100. 23/23 mailmap, quote: move declarations of global vars to correct unitElijah Newren, Apr 11, 2023
  101. Elijah NewrenApr 11, 2023

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.