2006-04-23 18:26:03 +00:00
|
|
|
/*
|
|
|
|
* Header for misc.c.
|
|
|
|
*/
|
|
|
|
|
2001-04-28 09:24:19 +00:00
|
|
|
#ifndef PUTTY_MISC_H
|
|
|
|
#define PUTTY_MISC_H
|
|
|
|
|
2018-05-24 07:59:01 +00:00
|
|
|
#include "defs.h"
|
2001-04-28 09:24:19 +00:00
|
|
|
#include "puttymem.h"
|
2018-05-24 08:17:13 +00:00
|
|
|
#include "marshal.h"
|
2001-04-28 09:24:19 +00:00
|
|
|
|
2004-11-27 13:20:21 +00:00
|
|
|
#include <stdio.h> /* for FILE * */
|
2002-11-07 19:49:03 +00:00
|
|
|
#include <stdarg.h> /* for va_list */
|
2019-01-03 08:12:19 +00:00
|
|
|
#include <stdlib.h> /* for abort */
|
2005-01-09 14:45:00 +00:00
|
|
|
#include <time.h> /* for struct tm */
|
2018-10-26 22:08:50 +00:00
|
|
|
#include <limits.h> /* for INT_MAX/MIN */
|
2019-01-03 08:12:19 +00:00
|
|
|
#include <assert.h> /* for assert (obviously) */
|
2002-11-07 19:49:03 +00:00
|
|
|
|
2004-12-24 13:39:32 +00:00
|
|
|
unsigned long parse_blocksize(const char *bs);
|
2005-04-19 18:58:29 +00:00
|
|
|
char ctrlparse(char *s, char **next);
|
2004-12-24 13:39:32 +00:00
|
|
|
|
2014-01-25 15:58:47 +00:00
|
|
|
size_t host_strcspn(const char *s, const char *set);
|
|
|
|
char *host_strchr(const char *s, int c);
|
|
|
|
char *host_strrchr(const char *s, int c);
|
|
|
|
char *host_strduptrim(const char *s);
|
|
|
|
|
2002-11-07 19:49:03 +00:00
|
|
|
char *dupstr(const char *s);
|
|
|
|
char *dupcat(const char *s1, ...);
|
2013-11-17 14:05:44 +00:00
|
|
|
char *dupprintf(const char *fmt, ...)
|
|
|
|
#ifdef __GNUC__
|
|
|
|
__attribute__ ((format (printf, 1, 2)))
|
|
|
|
#endif
|
|
|
|
;
|
2002-11-07 19:49:03 +00:00
|
|
|
char *dupvprintf(const char *fmt, va_list ap);
|
2011-10-02 14:03:47 +00:00
|
|
|
void burnstr(char *string);
|
2018-05-24 07:59:01 +00:00
|
|
|
|
2019-03-01 19:25:47 +00:00
|
|
|
/*
|
|
|
|
* The visible part of a strbuf structure. There's a surrounding
|
|
|
|
* implementation struct in misc.c, which isn't exposed to client
|
|
|
|
* code.
|
|
|
|
*/
|
2018-05-24 13:55:10 +00:00
|
|
|
struct strbuf {
|
|
|
|
char *s;
|
|
|
|
unsigned char *u;
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
size_t len;
|
2018-05-24 08:17:13 +00:00
|
|
|
BinarySink_IMPLEMENTATION;
|
2018-05-24 13:55:10 +00:00
|
|
|
};
|
2019-03-01 19:25:47 +00:00
|
|
|
|
|
|
|
/* strbuf constructors: strbuf_new_nm and strbuf_new differ in that a
|
|
|
|
* strbuf constructed using the _nm version will resize itself by
|
|
|
|
* alloc/copy/smemclr/free instead of realloc. Use that version for
|
|
|
|
* data sensitive enough that it's worth costing performance to
|
|
|
|
* avoid copies of it lingering in process memory. */
|
2017-01-21 14:55:53 +00:00
|
|
|
strbuf *strbuf_new(void);
|
2019-03-01 19:25:47 +00:00
|
|
|
strbuf *strbuf_new_nm(void);
|
|
|
|
|
2017-01-21 14:55:53 +00:00
|
|
|
void strbuf_free(strbuf *buf);
|
2018-06-08 18:07:47 +00:00
|
|
|
void *strbuf_append(strbuf *buf, size_t len);
|
2017-01-21 14:55:53 +00:00
|
|
|
char *strbuf_to_str(strbuf *buf); /* does free buf, but you must free result */
|
|
|
|
void strbuf_catf(strbuf *buf, const char *fmt, ...);
|
|
|
|
void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap);
|
2001-08-26 15:31:29 +00:00
|
|
|
|
2018-05-24 12:18:13 +00:00
|
|
|
strbuf *strbuf_new_for_agent_query(void);
|
|
|
|
void strbuf_finalise_agent_query(strbuf *buf);
|
|
|
|
|
2015-07-27 19:06:02 +00:00
|
|
|
/* String-to-Unicode converters that auto-allocate the destination and
|
|
|
|
* work around the rather deficient interface of mb_to_wc.
|
|
|
|
*
|
|
|
|
* These actually live in miscucs.c, not misc.c (the distinction being
|
|
|
|
* that the former is only linked into tools that also have the main
|
|
|
|
* Unicode support). */
|
|
|
|
wchar_t *dup_mb_to_wc_c(int codepage, int flags, const char *string, int len);
|
|
|
|
wchar_t *dup_mb_to_wc(int codepage, int flags, const char *string);
|
|
|
|
|
2018-10-26 22:08:50 +00:00
|
|
|
static inline int toint(unsigned u)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Convert an unsigned to an int, without running into the
|
|
|
|
* undefined behaviour which happens by the strict C standard if
|
|
|
|
* the value overflows. You'd hope that sensible compilers would
|
|
|
|
* do the sensible thing in response to a cast, but actually I
|
|
|
|
* don't trust modern compilers not to do silly things like
|
|
|
|
* assuming that _obviously_ you wouldn't have caused an overflow
|
|
|
|
* and so they can elide an 'if (i < 0)' test immediately after
|
|
|
|
* the cast.
|
|
|
|
*
|
|
|
|
* Sensible compilers ought of course to optimise this entire
|
|
|
|
* function into 'just return the input value', and since it's
|
|
|
|
* also declared inline, elide it completely in their output.
|
|
|
|
*/
|
|
|
|
if (u <= (unsigned)INT_MAX)
|
|
|
|
return (int)u;
|
|
|
|
else if (u >= (unsigned)INT_MIN) /* wrap in cast _to_ unsigned is OK */
|
|
|
|
return INT_MIN + (int)(u - (unsigned)INT_MIN);
|
|
|
|
else
|
|
|
|
return INT_MIN; /* fallback; should never occur on binary machines */
|
|
|
|
}
|
2013-07-14 10:45:54 +00:00
|
|
|
|
2004-11-27 13:20:21 +00:00
|
|
|
char *fgetline(FILE *fp);
|
2015-05-12 09:47:33 +00:00
|
|
|
char *chomp(char *str);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool strstartswith(const char *s, const char *t);
|
|
|
|
bool strendswith(const char *s, const char *t);
|
2004-11-27 13:20:21 +00:00
|
|
|
|
2015-05-12 13:00:04 +00:00
|
|
|
void base64_encode_atom(const unsigned char *data, int n, char *out);
|
|
|
|
int base64_decode_atom(const char *atom, unsigned char *out);
|
2002-09-21 14:03:05 +00:00
|
|
|
|
2001-08-25 17:09:23 +00:00
|
|
|
struct bufchain_granule;
|
2016-04-06 08:06:19 +00:00
|
|
|
struct bufchain_tag {
|
2001-08-25 17:09:23 +00:00
|
|
|
struct bufchain_granule *head, *tail;
|
2019-02-06 20:42:44 +00:00
|
|
|
size_t buffersize; /* current amount of buffered data */
|
Move standalone parts of misc.c into utils.c.
misc.c has always contained a combination of things that are tied
tightly into the PuTTY code base (e.g. they use the conf system, or
work with our sockets abstraction) and things that are pure standalone
utility functions like nullstrcmp() which could quite happily be
dropped into any C program without causing a link failure.
Now the latter kind of standalone utility code lives in the new source
file utils.c, whose only external dependency is on memory.c (for snew,
sfree etc), which in turn requires the user to provide an
out_of_memory() function. So it should now be much easier to link test
programs that use PuTTY's low-level functions without also pulling in
half its bulky infrastructure.
In the process, I came across a memory allocation logging system
enabled by -DMALLOC_LOG that looks long since bit-rotted; in any case
we have much more advanced tools for that kind of thing these days,
like valgrind and Leak Sanitiser, so I've just removed it rather than
trying to transplant it somewhere sensible. (We can always pull it
back out of the version control history if really necessary, but I
haven't used it in at least a decade.)
The other slightly silly thing I did was to give bufchain a function
pointer field that points to queue_idempotent_callback(), and disallow
direct setting of the 'ic' field in favour of calling
bufchain_set_callback which will fill that pointer in too. That allows
the bufchain system to live in utils.c rather than misc.c, so that
programs can use it without also having to link in the callback system
or provide an annoying stub of that function. In fact that's just
allowed me to remove stubs of that kind from PuTTYgen and Pageant!
2019-01-03 08:44:11 +00:00
|
|
|
|
|
|
|
void (*queue_idempotent_callback)(IdempotentCallback *ic);
|
2018-09-22 07:13:41 +00:00
|
|
|
IdempotentCallback *ic;
|
2016-04-06 08:06:19 +00:00
|
|
|
};
|
2001-08-25 17:09:23 +00:00
|
|
|
|
|
|
|
void bufchain_init(bufchain *ch);
|
|
|
|
void bufchain_clear(bufchain *ch);
|
2019-02-06 20:42:44 +00:00
|
|
|
size_t bufchain_size(bufchain *ch);
|
|
|
|
void bufchain_add(bufchain *ch, const void *data, size_t len);
|
2019-02-06 20:46:45 +00:00
|
|
|
ptrlen bufchain_prefix(bufchain *ch);
|
2019-02-06 20:42:44 +00:00
|
|
|
void bufchain_consume(bufchain *ch, size_t len);
|
|
|
|
void bufchain_fetch(bufchain *ch, void *data, size_t len);
|
|
|
|
void bufchain_fetch_consume(bufchain *ch, void *data, size_t len);
|
|
|
|
bool bufchain_try_fetch_consume(bufchain *ch, void *data, size_t len);
|
|
|
|
size_t bufchain_fetch_consume_up_to(bufchain *ch, void *data, size_t len);
|
Move standalone parts of misc.c into utils.c.
misc.c has always contained a combination of things that are tied
tightly into the PuTTY code base (e.g. they use the conf system, or
work with our sockets abstraction) and things that are pure standalone
utility functions like nullstrcmp() which could quite happily be
dropped into any C program without causing a link failure.
Now the latter kind of standalone utility code lives in the new source
file utils.c, whose only external dependency is on memory.c (for snew,
sfree etc), which in turn requires the user to provide an
out_of_memory() function. So it should now be much easier to link test
programs that use PuTTY's low-level functions without also pulling in
half its bulky infrastructure.
In the process, I came across a memory allocation logging system
enabled by -DMALLOC_LOG that looks long since bit-rotted; in any case
we have much more advanced tools for that kind of thing these days,
like valgrind and Leak Sanitiser, so I've just removed it rather than
trying to transplant it somewhere sensible. (We can always pull it
back out of the version control history if really necessary, but I
haven't used it in at least a decade.)
The other slightly silly thing I did was to give bufchain a function
pointer field that points to queue_idempotent_callback(), and disallow
direct setting of the 'ic' field in favour of calling
bufchain_set_callback which will fill that pointer in too. That allows
the bufchain system to live in utils.c rather than misc.c, so that
programs can use it without also having to link in the callback system
or provide an annoying stub of that function. In fact that's just
allowed me to remove stubs of that kind from PuTTYgen and Pageant!
2019-01-03 08:44:11 +00:00
|
|
|
void bufchain_set_callback_inner(
|
|
|
|
bufchain *ch, IdempotentCallback *ic,
|
|
|
|
void (*queue_idempotent_callback)(IdempotentCallback *ic));
|
|
|
|
static inline void bufchain_set_callback(bufchain *ch, IdempotentCallback *ic)
|
|
|
|
{
|
|
|
|
extern void queue_idempotent_callback(struct IdempotentCallback *ic);
|
|
|
|
/* Wrapper that puts in the standard queue_idempotent_callback
|
|
|
|
* function. Lives here rather than in utils.c so that standalone
|
|
|
|
* programs can use the bufchain facility without this optional
|
|
|
|
* callback feature and not need to provide a stub of
|
|
|
|
* queue_idempotent_callback. */
|
|
|
|
bufchain_set_callback_inner(ch, ic, queue_idempotent_callback);
|
|
|
|
}
|
2001-04-28 09:24:19 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool validate_manual_hostkey(char *key);
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
|
2005-01-09 14:27:48 +00:00
|
|
|
struct tm ltime(void);
|
|
|
|
|
2018-09-14 16:04:39 +00:00
|
|
|
/*
|
|
|
|
* Special form of strcmp which can cope with NULL inputs. NULL is
|
|
|
|
* defined to sort before even the empty string.
|
|
|
|
*/
|
|
|
|
int nullstrcmp(const char *a, const char *b);
|
|
|
|
|
2018-10-26 22:08:50 +00:00
|
|
|
static inline ptrlen make_ptrlen(const void *ptr, size_t len)
|
|
|
|
{
|
|
|
|
ptrlen pl;
|
|
|
|
pl.ptr = ptr;
|
|
|
|
pl.len = len;
|
|
|
|
return pl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline ptrlen ptrlen_from_asciz(const char *str)
|
|
|
|
{
|
|
|
|
return make_ptrlen(str, strlen(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline ptrlen ptrlen_from_strbuf(strbuf *sb)
|
|
|
|
{
|
|
|
|
return make_ptrlen(sb->u, sb->len);
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool ptrlen_eq_string(ptrlen pl, const char *str);
|
|
|
|
bool ptrlen_eq_ptrlen(ptrlen pl1, ptrlen pl2);
|
2019-01-01 19:07:00 +00:00
|
|
|
int ptrlen_strcmp(ptrlen pl1, ptrlen pl2);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool ptrlen_startswith(ptrlen whole, ptrlen prefix, ptrlen *tail);
|
2019-03-09 15:47:28 +00:00
|
|
|
bool ptrlen_endswith(ptrlen whole, ptrlen suffix, ptrlen *tail);
|
2018-05-27 15:56:51 +00:00
|
|
|
char *mkstr(ptrlen pl);
|
|
|
|
int string_length_for_printf(size_t);
|
|
|
|
/* Derive two printf arguments from a ptrlen, suitable for "%.*s" */
|
|
|
|
#define PTRLEN_PRINTF(pl) \
|
|
|
|
string_length_for_printf((pl).len), (const char *)(pl).ptr
|
2018-09-19 16:58:25 +00:00
|
|
|
/* Make a ptrlen out of a compile-time string literal. We try to
|
|
|
|
* enforce that it _is_ a string literal by token-pasting "" on to it,
|
|
|
|
* which should provoke a compile error if it's any other kind of
|
|
|
|
* string. */
|
|
|
|
#define PTRLEN_LITERAL(stringlit) \
|
|
|
|
TYPECHECK("" stringlit "", make_ptrlen(stringlit, sizeof(stringlit)-1))
|
2019-02-10 08:44:59 +00:00
|
|
|
/* Make a ptrlen out of a constant byte array. */
|
|
|
|
#define PTRLEN_FROM_CONST_BYTES(a) make_ptrlen(a, sizeof(a))
|
2018-05-27 15:56:51 +00:00
|
|
|
|
2015-04-26 22:31:11 +00:00
|
|
|
/* Wipe sensitive data out of memory that's about to be freed. Simpler
|
|
|
|
* than memset because we don't need the fill char parameter; also
|
|
|
|
* attempts (by fiddly use of volatile) to inhibit the compiler from
|
|
|
|
* over-cleverly trying to optimise the memset away because it knows
|
|
|
|
* the variable is going out of scope. */
|
2012-07-28 16:33:51 +00:00
|
|
|
void smemclr(void *b, size_t len);
|
|
|
|
|
2015-04-26 22:31:11 +00:00
|
|
|
/* Compare two fixed-length chunks of memory for equality, without
|
|
|
|
* data-dependent control flow (so an attacker with a very accurate
|
|
|
|
* stopwatch can't try to guess where the first mismatching byte was).
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
* Returns false for mismatch or true for equality (unlike memcmp),
|
|
|
|
* hinted at by the 'eq' in the name. */
|
|
|
|
bool smemeq(const void *av, const void *bv, size_t len);
|
2015-04-26 22:31:11 +00:00
|
|
|
|
2019-03-05 07:24:17 +00:00
|
|
|
/* Encode a single UTF-8 character. Assumes that illegal characters
|
|
|
|
* (such as things in the surrogate range, or > 0x10FFFF) have already
|
|
|
|
* been removed. */
|
|
|
|
size_t encode_utf8(void *output, unsigned long ch);
|
|
|
|
|
2017-01-21 14:55:53 +00:00
|
|
|
char *buildinfo(const char *newline);
|
|
|
|
|
2019-01-03 08:12:19 +00:00
|
|
|
/*
|
|
|
|
* A function you can put at points in the code where execution should
|
|
|
|
* never reach in the first place. Better than assert(false), or even
|
|
|
|
* assert(false && "some explanatory message"), because some compilers
|
|
|
|
* don't interpret assert(false) as a declaration of unreachability,
|
|
|
|
* so they may still warn about pointless things like some variable
|
|
|
|
* not being initialised on the unreachable code path.
|
|
|
|
*
|
|
|
|
* I follow the assertion with a call to abort() just in case someone
|
|
|
|
* compiles with -DNDEBUG, and I wrap that abort inside my own
|
|
|
|
* function labelled NORETURN just in case some unusual kind of system
|
|
|
|
* header wasn't foresighted enough to label abort() itself that way.
|
|
|
|
*/
|
|
|
|
static inline NORETURN void unreachable_internal(void) { abort(); }
|
|
|
|
#define unreachable(msg) (assert(false && msg), unreachable_internal())
|
|
|
|
|
2001-04-28 09:24:19 +00:00
|
|
|
/*
|
|
|
|
* Debugging functions.
|
|
|
|
*
|
|
|
|
* Output goes to debug.log
|
|
|
|
*
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
* debug() is like printf().
|
2001-04-28 09:24:19 +00:00
|
|
|
*
|
|
|
|
* dmemdump() and dmemdumpl() both do memory dumps. The difference
|
2005-03-24 01:01:24 +00:00
|
|
|
* is that dmemdumpl() is more suited for when the memory address is
|
2001-04-28 09:24:19 +00:00
|
|
|
* important (say because you'll be recording pointer values later
|
|
|
|
* on). dmemdump() is more concise.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2015-05-09 14:02:45 +00:00
|
|
|
void debug_printf(const char *fmt, ...);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
void debug_memdump(const void *buf, int len, bool L);
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
#define debug(...) (debug_printf(__VA_ARGS__))
|
2019-02-28 18:00:31 +00:00
|
|
|
#define dmemdump(buf,len) (debug_memdump(buf, len, false))
|
|
|
|
#define dmemdumpl(buf,len) (debug_memdump(buf, len, true))
|
2001-04-28 09:24:19 +00:00
|
|
|
#else
|
2019-02-28 18:00:31 +00:00
|
|
|
#define debug(...) ((void)0)
|
|
|
|
#define dmemdump(buf,len) ((void)0)
|
|
|
|
#define dmemdumpl(buf,len) ((void)0)
|
2001-04-28 09:24:19 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef lenof
|
|
|
|
#define lenof(x) ( (sizeof((x))) / (sizeof(*(x))))
|
|
|
|
#endif
|
|
|
|
|
2002-10-09 18:09:42 +00:00
|
|
|
#ifndef min
|
|
|
|
#define min(x,y) ( (x) < (y) ? (x) : (y) )
|
|
|
|
#endif
|
|
|
|
#ifndef max
|
2002-10-14 09:04:23 +00:00
|
|
|
#define max(x,y) ( (x) > (y) ? (x) : (y) )
|
2002-10-09 18:09:42 +00:00
|
|
|
#endif
|
2001-04-28 09:24:19 +00:00
|
|
|
|
2019-02-04 07:45:09 +00:00
|
|
|
static inline uint64_t GET_64BIT_LSB_FIRST(const void *vp)
|
|
|
|
{
|
|
|
|
const uint8_t *p = (const uint8_t *)vp;
|
|
|
|
return (((uint64_t)p[0] ) | ((uint64_t)p[1] << 8) |
|
|
|
|
((uint64_t)p[2] << 16) | ((uint64_t)p[3] << 24) |
|
|
|
|
((uint64_t)p[4] << 32) | ((uint64_t)p[5] << 40) |
|
|
|
|
((uint64_t)p[6] << 48) | ((uint64_t)p[7] << 56));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void PUT_64BIT_LSB_FIRST(void *vp, uint64_t value)
|
|
|
|
{
|
|
|
|
uint8_t *p = (uint8_t *)vp;
|
|
|
|
p[0] = value;
|
|
|
|
p[1] = (value) >> 8;
|
|
|
|
p[2] = (value) >> 16;
|
|
|
|
p[3] = (value) >> 24;
|
|
|
|
p[4] = (value) >> 32;
|
|
|
|
p[5] = (value) >> 40;
|
|
|
|
p[6] = (value) >> 48;
|
|
|
|
p[7] = (value) >> 56;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32_t GET_32BIT_LSB_FIRST(const void *vp)
|
|
|
|
{
|
|
|
|
const uint8_t *p = (const uint8_t *)vp;
|
|
|
|
return (((uint32_t)p[0] ) | ((uint32_t)p[1] << 8) |
|
|
|
|
((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void PUT_32BIT_LSB_FIRST(void *vp, uint32_t value)
|
|
|
|
{
|
|
|
|
uint8_t *p = (uint8_t *)vp;
|
|
|
|
p[0] = value;
|
|
|
|
p[1] = (value) >> 8;
|
|
|
|
p[2] = (value) >> 16;
|
|
|
|
p[3] = (value) >> 24;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint16_t GET_16BIT_LSB_FIRST(const void *vp)
|
|
|
|
{
|
|
|
|
const uint8_t *p = (const uint8_t *)vp;
|
|
|
|
return (((uint16_t)p[0] ) | ((uint16_t)p[1] << 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void PUT_16BIT_LSB_FIRST(void *vp, uint16_t value)
|
|
|
|
{
|
|
|
|
uint8_t *p = (uint8_t *)vp;
|
|
|
|
p[0] = value;
|
|
|
|
p[1] = (value) >> 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint64_t GET_64BIT_MSB_FIRST(const void *vp)
|
|
|
|
{
|
|
|
|
const uint8_t *p = (const uint8_t *)vp;
|
|
|
|
return (((uint64_t)p[7] ) | ((uint64_t)p[6] << 8) |
|
|
|
|
((uint64_t)p[5] << 16) | ((uint64_t)p[4] << 24) |
|
|
|
|
((uint64_t)p[3] << 32) | ((uint64_t)p[2] << 40) |
|
|
|
|
((uint64_t)p[1] << 48) | ((uint64_t)p[0] << 56));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void PUT_64BIT_MSB_FIRST(void *vp, uint64_t value)
|
|
|
|
{
|
|
|
|
uint8_t *p = (uint8_t *)vp;
|
|
|
|
p[7] = value;
|
|
|
|
p[6] = (value) >> 8;
|
|
|
|
p[5] = (value) >> 16;
|
|
|
|
p[4] = (value) >> 24;
|
|
|
|
p[3] = (value) >> 32;
|
|
|
|
p[2] = (value) >> 40;
|
|
|
|
p[1] = (value) >> 48;
|
|
|
|
p[0] = (value) >> 56;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint32_t GET_32BIT_MSB_FIRST(const void *vp)
|
|
|
|
{
|
|
|
|
const uint8_t *p = (const uint8_t *)vp;
|
|
|
|
return (((uint32_t)p[3] ) | ((uint32_t)p[2] << 8) |
|
|
|
|
((uint32_t)p[1] << 16) | ((uint32_t)p[0] << 24));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void PUT_32BIT_MSB_FIRST(void *vp, uint32_t value)
|
|
|
|
{
|
|
|
|
uint8_t *p = (uint8_t *)vp;
|
|
|
|
p[3] = value;
|
|
|
|
p[2] = (value) >> 8;
|
|
|
|
p[1] = (value) >> 16;
|
|
|
|
p[0] = (value) >> 24;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint16_t GET_16BIT_MSB_FIRST(const void *vp)
|
|
|
|
{
|
|
|
|
const uint8_t *p = (const uint8_t *)vp;
|
|
|
|
return (((uint16_t)p[1] ) | ((uint16_t)p[0] << 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void PUT_16BIT_MSB_FIRST(void *vp, uint16_t value)
|
|
|
|
{
|
|
|
|
uint8_t *p = (uint8_t *)vp;
|
|
|
|
p[1] = value;
|
|
|
|
p[0] = (value) >> 8;
|
|
|
|
}
|
2005-04-12 20:04:56 +00:00
|
|
|
|
2016-02-29 19:38:12 +00:00
|
|
|
/* Replace NULL with the empty string, permitting an idiom in which we
|
|
|
|
* get a string (pointer,length) pair that might be NULL,0 and can
|
|
|
|
* then safely say things like printf("%.*s", length, NULLTOEMPTY(ptr)) */
|
2019-02-04 07:45:09 +00:00
|
|
|
static inline const char *NULLTOEMPTY(const char *s)
|
|
|
|
{
|
|
|
|
return s ? s : "";
|
|
|
|
}
|
2016-02-29 19:38:12 +00:00
|
|
|
|
New utility object, StripCtrlChars.
This is for sanitising output that's going to be sent to a terminal,
if you don't want it to be able to send arbitrary escape sequences and
thereby (for example) move the cursor back up to existing text on the
screen and overprint it confusingly.
It works using the standard C library: we convert to a wide-character
string and back, and then use wctype.h to spot control characters in
the intermediate form. This means its idea of the conversion character
set is locale-based rather than any of our own charset library's fixed
settings - which is what you want if the aim is to protect your local
terminal (which we assume the system locale represents accurately).
This also means that the sanitiser strips things that will _act_ as
control characters when sent to the local terminal, whether or not
they were intended as control characters by a server that might have
had a different character set in mind. Since the main aim is to
protect the local terminal rather than to faithfully replicate the
server's intention, I think that's the right criterion.
It only strips control characters at the charset-independent layer,
like backspace, carriage return and the escape character: wctype.h
classifies those as control characters, but classifies as printing all
of the more Unicode-specific controls like bidirectional overrides.
But that's enough to prevent cursor repositioning, for example.
stripctrl.c comes with a test main() of its own, which I wasn't able
to fold into testcrypt and put in the test suite because of its
dependence on the system locale - it wouldn't be guaranteed to work
the same way on different test systems anyway.
A knock-on build tweak: because you can feed data into this sanitiser
in chunks of arbitrary size, including partial multibyte chars, I had
to use mbrtowc() for the decoding, and that means that in the 'old'
Win32 builds I have to link against the Visual Studio C++ library as
well as the C library, because for some reason that's where mbrtowc
lived in VS2003.
2019-02-20 06:56:40 +00:00
|
|
|
/* StripCtrlChars, defined in stripctrl.c: an adapter you can put on
|
|
|
|
* the front of one BinarySink and which functions as one in turn.
|
|
|
|
* Interprets its input as a stream of multibyte characters in the
|
|
|
|
* system locale, and removes any that are not either printable
|
|
|
|
* characters or newlines. */
|
|
|
|
struct StripCtrlChars {
|
|
|
|
BinarySink_IMPLEMENTATION;
|
|
|
|
/* and this is contained in a larger structure */
|
|
|
|
};
|
|
|
|
StripCtrlChars *stripctrl_new(
|
|
|
|
BinarySink *bs_out, bool permit_cr, wchar_t substitution);
|
2019-03-04 20:58:44 +00:00
|
|
|
StripCtrlChars *stripctrl_new_term_fn(
|
|
|
|
BinarySink *bs_out, bool permit_cr, wchar_t substitution,
|
|
|
|
Terminal *term, unsigned long (*translate)(
|
|
|
|
Terminal *, term_utf8_decode *, unsigned char));
|
|
|
|
#define stripctrl_new_term(bs, cr, sub, term) \
|
|
|
|
stripctrl_new_term_fn(bs, cr, sub, term, term_translate)
|
2019-03-09 15:50:38 +00:00
|
|
|
void stripctrl_retarget(StripCtrlChars *sccpub, BinarySink *new_bs_out);
|
|
|
|
void stripctrl_reset(StripCtrlChars *sccpub);
|
New utility object, StripCtrlChars.
This is for sanitising output that's going to be sent to a terminal,
if you don't want it to be able to send arbitrary escape sequences and
thereby (for example) move the cursor back up to existing text on the
screen and overprint it confusingly.
It works using the standard C library: we convert to a wide-character
string and back, and then use wctype.h to spot control characters in
the intermediate form. This means its idea of the conversion character
set is locale-based rather than any of our own charset library's fixed
settings - which is what you want if the aim is to protect your local
terminal (which we assume the system locale represents accurately).
This also means that the sanitiser strips things that will _act_ as
control characters when sent to the local terminal, whether or not
they were intended as control characters by a server that might have
had a different character set in mind. Since the main aim is to
protect the local terminal rather than to faithfully replicate the
server's intention, I think that's the right criterion.
It only strips control characters at the charset-independent layer,
like backspace, carriage return and the escape character: wctype.h
classifies those as control characters, but classifies as printing all
of the more Unicode-specific controls like bidirectional overrides.
But that's enough to prevent cursor repositioning, for example.
stripctrl.c comes with a test main() of its own, which I wasn't able
to fold into testcrypt and put in the test suite because of its
dependence on the system locale - it wouldn't be guaranteed to work
the same way on different test systems anyway.
A knock-on build tweak: because you can feed data into this sanitiser
in chunks of arbitrary size, including partial multibyte chars, I had
to use mbrtowc() for the decoding, and that means that in the 'old'
Win32 builds I have to link against the Visual Studio C++ library as
well as the C library, because for some reason that's where mbrtowc
lived in VS2003.
2019-02-20 06:56:40 +00:00
|
|
|
void stripctrl_free(StripCtrlChars *sanpub);
|
|
|
|
char *stripctrl_string_ptrlen(ptrlen str);
|
|
|
|
static inline char *stripctrl_string(const char *str)
|
|
|
|
{
|
|
|
|
return stripctrl_string_ptrlen(ptrlen_from_asciz(str));
|
|
|
|
}
|
|
|
|
|
2001-04-28 09:24:19 +00:00
|
|
|
#endif
|