Skip to content

Commit

Permalink
Add regexp support on Windows using std::regex
Browse files Browse the repository at this point in the history
Provide glue code in libkrb5support to emulate the POSIX regex(3)
interface by calling into the C++ std::regex classes.

Eliminate compatibility code for pre-POSIX regex functions.

[ghudson@mit.edu: additional cleanup of regexp callers; minor style
adjustments; removed regerrlen field; edited commit message]
  • Loading branch information
Ken Hornstein authored and greghudson committed Dec 20, 2024
1 parent 27d1775 commit d70692e
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 235 deletions.
48 changes: 0 additions & 48 deletions src/aclocal.m4
Original file line number Diff line number Diff line change
Expand Up @@ -714,53 +714,6 @@ KRB5_NEED_PROTO([#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif],daemon,1)])dnl

dnl
dnl KRB5_AC_NEED_LIBGEN --- check if libgen needs to be linked in for
dnl compile/step
dnl
dnl
AC_DEFUN(KRB5_AC_NEED_LIBGEN,[
AC_REQUIRE([AC_PROG_CC])dnl
dnl
dnl regcomp is present but non-functional on Solaris 2.4
dnl
AC_MSG_CHECKING(for working regcomp)
AC_CACHE_VAL(ac_cv_func_regcomp,
[AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <sys/types.h>
#include <regex.h>
regex_t x; regmatch_t m;]],
[[return regcomp(&x,"pat.*",0) || regexec(&x,"pattern",1,&m,0);]])],
[ac_cv_func_regcomp=yes], [ac_cv_func_regcomp=no],
[AC_MSG_ERROR([Cannot test regcomp when cross compiling])])])
AC_MSG_RESULT($ac_cv_func_regcomp)
test $ac_cv_func_regcomp = yes && AC_DEFINE(HAVE_REGCOMP,1,[Define if regcomp exists and functions])
dnl
dnl Check for the compile and step functions - only if regcomp is not available
dnl
if test $ac_cv_func_regcomp = no; then
save_LIBS="$LIBS"
LIBS=-lgen
dnl this will fail if there's no compile/step in -lgen, or if there's
dnl no -lgen. This is fine.
AC_CHECK_FUNCS(compile step)
LIBS="$save_LIBS"
dnl
dnl Set GEN_LIB if necessary
dnl
AC_CHECK_LIB(gen, compile, GEN_LIB=-lgen, GEN_LIB=)
AC_SUBST(GEN_LIB)
fi
])
dnl
dnl KRB5_AC_REGEX_FUNCS --- check for different regular expression
dnl support functions
dnl
AC_DEFUN(KRB5_AC_REGEX_FUNCS,[
AC_CHECK_FUNCS(re_comp re_exec regexec)
AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl
])dnl
dnl
dnl WITH_HESIOD
dnl
Expand Down Expand Up @@ -850,7 +803,6 @@ dnl Set variables to build a program.

AC_DEFUN(KRB5_BUILD_PROGRAM,
[AC_REQUIRE([KRB5_LIB_AUX])dnl
AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl
AC_SUBST(CC_LINK)
AC_SUBST(CXX_LINK)
AC_SUBST(RPATH_FLAG)
Expand Down
4 changes: 1 addition & 3 deletions src/build-tools/krb5-config.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ DEFKTNAME='@DEFKTNAME@'
DEFCKTNAME='@DEFCKTNAME@'

LIBS='@LIBS@'
GEN_LIB=@GEN_LIB@

# Defaults for program
library=krb5
Expand Down Expand Up @@ -253,8 +252,7 @@ if test -n "$do_libs"; then
fi

# If we ever support a flag to generate output suitable for static
# linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB"
# here.
# linking, we would output "-lkrb5support $LIBS $DL_LIB" here.

echo $lib_flags
fi
Expand Down
5 changes: 1 addition & 4 deletions src/config/pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,6 @@ VERTO_DEPS-k5 = $(BUILDTOP)/include/verto.h

# LIBS gets substituted in... e.g. -lnsl -lsocket

# GEN_LIB is -lgen if needed for regexp
GEN_LIB = @GEN_LIB@

# Editline or readline flags and libraries.
RL_CFLAGS = @RL_CFLAGS@
RL_LIBS = @RL_LIBS@
Expand Down Expand Up @@ -380,7 +377,7 @@ SUPPORT_LIB = -l$(SUPPORT_LIBNAME)
# HESIOD_LIBS is -lhesiod...
HESIOD_LIBS = @HESIOD_LIBS@

KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(LIBS) $(DL_LIB)
KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS)
GSS_LIBS = $(GSS_KRB5_LIB)
# needs fixing if ever used on macOS!
Expand Down
11 changes: 1 addition & 10 deletions src/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -490,18 +490,9 @@ AC_SUBST(GETTIMEOFDAY_ST_OBJ)
AC_SUBST(EXTRA_SUPPORT_SYMS)

DECLARE_SYS_ERRLIST
AC_CHECK_HEADERS(unistd.h paths.h regex.h regexpr.h fcntl.h memory.h ifaddrs.h sys/filio.h byteswap.h machine/endian.h machine/byte_order.h sys/bswap.h endian.h pwd.h arpa/inet.h alloca.h dlfcn.h limits.h sys/random.h)
AC_CHECK_HEADER(regexp.h, [], [],
[#define INIT char *sp = instring;
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(c) return(c)
#define ERROR(c)
])
AC_CHECK_HEADERS(unistd.h paths.h fcntl.h memory.h ifaddrs.h sys/filio.h byteswap.h machine/endian.h machine/byte_order.h sys/bswap.h endian.h pwd.h arpa/inet.h alloca.h dlfcn.h limits.h sys/random.h)
AC_CHECK_MEMBERS([struct stat.st_mtimensec,struct stat.st_mtimespec.tv_nsec,struct stat.st_mtim.tv_nsec],,,[#include <sys/types.h>
#include <sys/stat.h>])
KRB5_AC_REGEX_FUNCS
AC_TYPE_OFF_T

# Fancy caching of perror result...
Expand Down
8 changes: 8 additions & 0 deletions src/include/k5-platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@
#include <unistd.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _WIN32
#define CAN_COPY_VA_LIST
#endif
Expand Down Expand Up @@ -1151,4 +1155,8 @@ extern char *k5_secure_getenv(const char *name);
int k5_dir_filenames(const char *dirname, char ***fnames_out);
void k5_free_filenames(char **fnames);

#ifdef __cplusplus
}
#endif

#endif /* K5_PLATFORM_H */
118 changes: 118 additions & 0 deletions src/include/k5-regex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* include/k5-regex.h - Compatibility glue for std::regex on Windows */

/*
* Copyright (C) 2024 United States Government as represented by the
* Secretary of the Navy.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* On POSIX platforms we can use the standardized regcomp()/regexec() function
* calls. Windows does not provide POSIX regex functions, but does provide a
* C++ interface (std::regex) that has the same functionality.
*/

#ifndef _K5_REGEX_H_
#define _K5_REGEX_H_

#ifndef _WIN32

/* On POSIX platforms, just include regex.h. */
#include <regex.h>

#else /* _WIN32 */

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* On Windows, emulate the POSIX interface using functions from
* libkrb5support. */

typedef struct {
size_t re_nsub; /* Number of subexpressions */
void *regex; /* Pointer to std::basic_regex */
char errmsg[128]; /* Regular expression error message */
} regex_t;

typedef ssize_t regoff_t;

typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
} regmatch_t;

/*
* Flags to k5_regcomp()
*/

#define REG_BASIC 0x00 /* Basic regular expressions */
#define REG_EXTENDED 0x01 /* Extended regular expressions */
#define REG_ICASE 0x02 /* Case-insensitive match */
#define REG_NOSUB 0x04 /* Do not do submatching */

/*
* Flags to k5_regexec()
*/

#define REG_NOTBOL 0x01 /* First character not at beginning of line */
#define REG_NOTEOL 0x02 /* Last character not at end of line */

/*
* Error return codes for k5_regcomp()/k5_regexec()
*
* We only define REG_NOMATCH and REG_BADPAT, since no Kerberos code looks
* for anything other than success and REG_NOMATCH.
*/

#define REG_NOMATCH 1
#define REG_BADPAT 2

/*
* Note that we don't follow the POSIX API exactly because k5_regexec()
* doesn't declare regex_t as const; that's so we can store an error
* string.
*/
int k5_regcomp(regex_t *preg, const char *pattern, int flags);
int k5_regexec(regex_t *preg, const char *string, size_t,
regmatch_t pmatch[], int flags);
size_t k5_regerror(int code, const regex_t *preg, char *errmsg,
size_t errmsg_size);
void k5_regfree(regex_t *preg);

#define regcomp k5_regcomp
#define regexec k5_regexec
#define regerror k5_regerror
#define regfree k5_regfree

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _WIN32 */
#endif /* _K5_REGEX_H_ */
47 changes: 1 addition & 46 deletions src/kadmin/dbutil/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@
#include <kdb.h>
#include <com_err.h>
#include "kdb5_util.h"
#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP)
#include <regex.h>
#endif /* HAVE_REGEX_H */
#include "k5-regex.h"

/* Needed for master key conversion. */
static krb5_boolean mkey_convert;
Expand All @@ -47,18 +45,6 @@ krb5_kvno new_mkvno;
#define K5Q(x) K5Q1(x)
#define K5CONST_WIDTH_SCANF_STR(x) "%" K5Q(x) "s"

/* Use compile(3) if no regcomp present. */
#if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H)
#define INIT char *sp = instring;
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(c) return(c)
#define ERROR(c)
#define RE_BUF_SIZE 1024
#include <regexp.h>
#endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */

typedef krb5_error_code (*dump_func)(krb5_context context,
krb5_db_entry *entry, const char *name,
FILE *fp, krb5_boolean verbose,
Expand Down Expand Up @@ -236,23 +222,15 @@ update_ok_file(krb5_context context, int fd)
static int
name_matches(char *name, struct dump_args *args)
{
#if HAVE_REGCOMP
regex_t reg;
regmatch_t rmatch;
int st;
char errmsg[BUFSIZ];
#elif HAVE_REGEXP_H
char regexp_buffer[RE_BUF_SIZE];
#elif HAVE_RE_COMP
extern char *re_comp();
char *re_result;
#endif /* HAVE_RE_COMP */
int i, match;

/* Check each regular expression in args. */
match = args->nnames ? 0 : 1;
for (i = 0; i < args->nnames && !match; i++) {
#if HAVE_REGCOMP
/* Compile the regular expression. */
st = regcomp(&reg, args->names[i], REG_EXTENDED);
if (st) {
Expand All @@ -274,29 +252,6 @@ name_matches(char *name, struct dump_args *args)
break;
}
regfree(&reg);
#elif HAVE_REGEXP_H
/* Compile the regular expression. */
compile(args->names[i], regexp_buffer, &regexp_buffer[RE_BUF_SIZE],
'\0');
if (step(name, regexp_buffer)) {
if (loc1 == name && loc2 == &name[strlen(name)])
match = 1;
}
#elif HAVE_RE_COMP
/* Compile the regular expression. */
re_result = re_comp(args->names[i]);
if (re_result) {
fprintf(stderr, _("%s: regular expression error: %s\n"), progname,
re_result);
break;
}
if (re_exec(name))
match = 1;
#else /* HAVE_RE_COMP */
/* If no regular expression support, then just compare the strings. */
if (!strcmp(args->names[i], name))
match = 1;
#endif /* HAVE_REGCOMP */
}
return match;
}
Expand Down
Loading

0 comments on commit d70692e

Please sign in to comment.