From 60031538ecbf9004ae195114cc5e4ea40cca7d06 Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Tue, 4 Oct 2016 20:01:49 +0200
Subject: [PATCH] Improve portability for regex

Do not depend on internal, platform dependant field in regex_t to detect
if the regex was compiled or not. Instead, use a flag that we set for
that.

This fixes build with musl libc.
---
 src/garden.h     | 11 ++++++++---
 src/main-redir.c | 26 +++++++++++---------------
 src/options.c    | 27 +++++++++++++++------------
 3 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/src/garden.h b/src/garden.h
index 1b07a23..84563e9 100644
--- a/src/garden.h
+++ b/src/garden.h
@@ -39,13 +39,18 @@ typedef struct pass_through_t {
     (a)->port        == (b)->port)
 
 #ifdef ENABLE_CHILLIREDIR
+struct chilli_regex {
+  regex_t re;
+  char allocated:1;
+};
+
 typedef struct regex_pass_through_t {
   char regex_host[512];
   char regex_path[512];
   char regex_qs[512];
-  regex_t re_host;
-  regex_t re_path;
-  regex_t re_qs;
+  struct chilli_regex re_host;
+  struct chilli_regex re_path;
+  struct chilli_regex re_qs;
   uint8_t inuse:1;
   uint8_t neg_host:1;
   uint8_t neg_path:1;
diff --git a/src/main-redir.c b/src/main-redir.c
index c7b0f07..001f882 100644
--- a/src/main-redir.c
+++ b/src/main-redir.c
@@ -501,29 +501,25 @@ static int redir_conn_read(struct conn_t *conn, void *ctx) {
 }
 
 static int
-check_regex(regex_t *re, char *regex, char *s) {
+check_regex(struct chilli_regex *re, char *regex, char *s) {
   int ret;
 
 #if(_debug_)
   syslog(LOG_DEBUG, "Checking %s =~ %s", s, regex);
 #endif
 
-#if defined (__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
-  if (!re->re_g)
-#else
-    if (!re->allocated)
-#endif
-    {
-      if ((ret = regcomp(re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
-        char error[512];
-        regerror(ret, re, error, sizeof(error));
-        syslog(LOG_ERR, "regcomp(%s) failed (%s)", regex, error);
-        regex[0] = 0;
-        return -1;
-      }
+  if (!re->allocated) {
+    if ((ret = regcomp(&re->re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
+      char error[512];
+      regerror(ret, &re->re, error, sizeof(error));
+      syslog(LOG_ERR, "regcomp(%s) failed (%s)", regex, error);
+      regex[0] = 0;
+      return -1;
     }
+    re->allocated = 1;
+  }
 
-  if ((ret = regexec(re, s, 0, 0, 0)) == 0) {
+  if ((ret = regexec(&re->re, s, 0, 0, 0)) == 0) {
 
     syslog(LOG_DEBUG, "Matched regex %s", regex);
     return 0;
diff --git a/src/options.c b/src/options.c
index 28f1b35..d6be8d0 100644
--- a/src/options.c
+++ b/src/options.c
@@ -219,6 +219,16 @@ int options_mkdir(char *path) {
   return 0;
 }
 
+#ifdef ENABLE_CHILLIREDIR
+static void chilli_regfree(struct chilli_regex *re)
+{
+  if (!re->allocated)
+    return;
+  regfree(&re->re);
+  re->allocated = 0;
+}
+#endif
+
 int options_fromfd(int fd, bstring bt) {
   uint8_t cksum[16], cksum_check[16];
   struct options_t o;
@@ -380,18 +390,11 @@ int options_fromfd(int fd, bstring bt) {
 
 #ifdef ENABLE_CHILLIREDIR
   for (i = 0; i < MAX_REGEX_PASS_THROUGHS; i++) {
-#if defined (__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
-    regfree(&_options.regex_pass_throughs[i].re_host);
-    regfree(&_options.regex_pass_throughs[i].re_path);
-    regfree(&_options.regex_pass_throughs[i].re_qs);
-#else
-    if (_options.regex_pass_throughs[i].re_host.allocated)
-      regfree(&_options.regex_pass_throughs[i].re_host);
-    if (_options.regex_pass_throughs[i].re_path.allocated)
-      regfree(&_options.regex_pass_throughs[i].re_path);
-    if (_options.regex_pass_throughs[i].re_qs.allocated)
-      regfree(&_options.regex_pass_throughs[i].re_qs);
-#endif
+    if (_options.regex_pass_throughs[i].re_host.allocated) {
+      chilli_regfree(&_options.regex_pass_throughs[i].re_host);
+      chilli_regfree(&_options.regex_pass_throughs[i].re_path);
+      chilli_regfree(&_options.regex_pass_throughs[i].re_qs);
+    }
   }
 #endif
 
-- 
2.10.0

