Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * pg_parse_lsn.c
4 : : * Parse a WAL location (LSN) in its text form.
5 : : *
6 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : * IDENTIFICATION
10 : : * src/common/pg_parse_lsn.c
11 : : *
12 : : *-------------------------------------------------------------------------
13 : : */
14 : :
15 : : #ifndef FRONTEND
16 : : #include "postgres.h"
17 : : #else
18 : : #include "postgres_fe.h"
19 : : #endif
20 : :
21 : : #include "common/pg_parse_lsn.h"
22 : :
23 : : #define MAXPG_LSNCOMPONENT 8
24 : :
25 : : /*
26 : : * pg_parse_lsn
27 : : *
28 : : * Parse a WAL location in the "%X/%X" text form used for pg_lsn values,
29 : : * requiring one to eight hexadecimal digits in each component and nothing
30 : : * else. Unlike sscanf(), this rejects components longer than eight
31 : : * hexadecimal digits, leading whitespace, signs, "0x" prefixes, and
32 : : * trailing characters.
33 : : *
34 : : * Returns true and sets *result on success; returns false on syntax
35 : : * error, leaving *result unchanged.
36 : : */
37 : : bool
38 : 5921 : pg_parse_lsn(const char *str, XLogRecPtr *result)
39 : : {
40 : : size_t len1,
41 : : len2;
42 : :
43 : 5921 : len1 = strspn(str, "0123456789abcdefABCDEF");
44 [ + + + + : 5921 : if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
+ + ]
45 : 32 : return false;
46 : :
47 : 5889 : len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
48 [ + + + + : 5889 : if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0')
+ + ]
49 : 9 : return false;
50 : :
51 : 5880 : *result = ((uint64) strtoul(str, NULL, 16)) << 32 |
52 : 5880 : (uint32) strtoul(str + len1 + 1, NULL, 16);
53 : :
54 : 5880 : return true;
55 : : }
|