908 Commits

Author SHA1 Message Date
Alejandro Colomar
8821d3ff2d lib/fs/readlink/: readlinknul(): Fix return type
Fixes: 419ce14b6f (2024-11-01, "lib/fs/readlink/: readlinknul(): Add function")
Cc: Serge Halyn <serge@hallyn.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 21:26:00 -06:00
Alejandro Colomar
b9d00b64a1 lib/fs/readlink/readlinknul.h: readlinknul(): Silence warning
Use a temporary variable to silence a sign-mismatch diagnostic.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 21:26:00 -06:00
Alejandro Colomar
c39305569b lib/, src/: Use !streq() instead of its pattern
Except for the added (and sorted) includes, the removal of redundant
parentheses, and a few non-string cases that I've left out of the
change, this patch can be approximated with the following semantic
patch:

	$ cat ~/tmp/spatch/strneq.sp
	@@
	expression s;
	@@

	- '\0' != *s
	+ !streq(s, "")

	@@
	expression s;
	@@

	- '\0' != s[0]
	+ !streq(s, "")

	@@
	expression s;
	@@

	- *s != '\0'
	+ !streq(s, "")

	@@
	expression s;
	@@

	- s[0] != '\0'
	+ !streq(s, "")

	$ find contrib/ lib* src/ -type f \
	| xargs spatch --in-place --sp-file ~/tmp/spatch/strneq.sp;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 20:54:42 -06:00
Alejandro Colomar
7182d6402f lib/, src/: Use streq() instead of its pattern
Except for the added (and sorted) includes, the removal of redundant
parentheses, a few cases that have been refactored for readability, and
a couple of non-string cases that I've left out of the change, this
patch can be approximated with the following semantic patch:

	$ cat ~/tmp/spatch/streq.sp
	@@
	expression s;
	@@

	- '\0' == *s
	+ streq(s, "")

	@@
	expression s;
	@@

	- '\0' == s[0]
	+ streq(s, "")

	@@
	expression s;
	@@

	- *s == '\0'
	+ streq(s, "")

	@@
	expression s;
	@@

	- s[0] == '\0'
	+ streq(s, "")

	$ find contrib/ lib* src/ -type f \
	| xargs spatch --in-place --sp-file ~/tmp/spatch/streq.sp;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 20:54:42 -06:00
Alejandro Colomar
8424d7c494 lib/sgetgrent.c: sgetgrent(): Fix use-after-free bug
We were reusing a leftover from parsing a previous line if
(i == NFIELDS-1).  A few lines below this check, we use read the element
in [3] (that is, [NFIELDS-1]), without having written it in this call.

Be stricter, and require that all NFIELDS fields are found.

Fixes: 45c6603cc8 (2007-10-07, "[svn-upgrade] Integrating new upstream version, shadow (19990709)")
Closes: <https://github.com/shadow-maint/shadow/issues/1144>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-09 19:46:29 -06:00
Alejandro Colomar
2f74389334 lib/gshadow.c: build_list(): Transform while loop into for loop
And 'n' is now an iterator.  Rename it to 'i' as usual.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
512deecca5 lib/gshadow.c: build_list(): Allocate at once
Instead of reallocating 1 more meber per iteration, calculate the total
amount that we want by counting the number of commas (delimiters) in the
string, plus one for the last element, plus one for the terminating
NULL.

This might result in overallocation of one element if the string is an
empty string, or if there's a trailing comma; however, that's not an
issue.  We can afford overallocating one element in certain cases, and
we get in exchange a much simpler function.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
2f4b5f5d80 lib/gshadow.c: Remove redundant variables
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
5ba62265b3 lib/gshadow.c: build_list(): Remove second parameter
We've simplified the function so much in the previous commits, that now
$2 is rather useless.  It only sets the output parameter to the same
value that the function returns.  It's simpler if the caller just sets
it itself after the call.

This removes the only 3-star pointer in the entire project.  :)

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
c1d597acbb lib/gshadow.c: sgetsgent(): Be consistent using NULL
0 is a horrible null-pointer constant.  Don't use it.
Especially, when just a few lines above, in the same function,
we've used NULL for the same thing.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
64ab7221fb lib/gshadow.c: build_list(): Compact ++ into previous statement
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
3feff7ae5b lib/gshadow.c: build_list(): Minimize use of pointer parameters
Use instead automatic variables as much as possible.
This reduces the number of dereferences, enhancing readability.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
30bcd185c3 lib/gshadow.c: Remove dead code
Nothing is using that value outside of build_list().
Keep it as an local variable.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
ecce8f098d lib/gshadow.c: Move zeroing to within build_list()
This makes build_list() less dependent on the context.
It starts from clean, whatever the state before the call was.
I was having a hard time understanding the reallocation,
until I saw that we were zeroing everything right before the call.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
712278add1 lib/gshadow.c: sgetsgent(): Remove superfluous condition
If n was 0, it doesn't hurt to set it again to 0;
and the list would be NULL, so it doesn't hurt free(3)ing it
and setting to NULL again either.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
de4715d978 lib/gshadow.c: build_list(): Remove dead assignment
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
f3464103fb lib/gshadow.c: build_list(): Improve variable and parameter names
It was hard to understand what each variable is.  Use a consistent
scheme, where a 'p' means a pointer, 'l' means list, and 'n' means
number of elements.  Those should be obvious from the name of the
function and the context, and will make it easier to read the code.
Also, the shorter names will allow focusing on the rest of the code.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
93887b4de6 lib/gshadow.c: build_list(): Remove unused variable
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
960947135c lib/gshadow.c: build_list(): Fix type of parameter
list ($2) is a pointer to a list of strings.  We were declaring it as an
array of pointers to strings, which was bogus.  It worked out of luck,
because array parameters are transformed into pointers by the compiler,
but it was incorrect.  Just look at how we're calling this function.

	$ grep build_list lib/gshadow.c
	build_list(char *s, char ***list, size_t *nlist)
		sgroup.sg_adm = build_list (fields[2], &admins, &nadmins);
		sgroup.sg_mem = build_list (fields[3], &members, &nmembers);
	$ grep '^static .*\<admins\>' lib/gshadow.c
	static /*@null@*//*@only@*/char **admins = NULL;
	$ grep '^static .*\<members\>' lib/gshadow.c
	static /*@null@*//*@only@*/char **members = NULL;

Fixes: 8e167d28af ("[svn-upgrade] Integrating new upstream version, shadow (4.0.8)")
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 21:20:59 -06:00
Alejandro Colomar
90afe61003 lib/, src/: Use strsep(3) instead of strtok(3)
strsep(3) is stateless, and so is easier to reason about.

It also has a slight difference: strtok(3) jumps over empty fields,
while strsep(3) respects them as empty fields.  In most of the cases
where we were using strtok(3), it makes more sense to respect empty
fields, and this commit probably silently fixes a few bugs.

In other cases (most notably filesystem paths), contiguous delimiters
("//") should be collapsed, so strtok(3) still makes more sense there.
This commit doesn't replace such strtok(3) calls.

While at this, remove some useless variables used by these calls, and
reduce the scope of others.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-05 15:33:32 -06:00
Alejandro Colomar
9f129146ff lib/, src/: Use !streq() instead of its pattern
Except for the added (and sorted) includes, and the removal of redundant
parentheses, and one special case, this patch can be approximated with
the following semantic patch:

	$ cat ~/tmp/spatch/strneq.sp;
	@@
	expression a, b;
	@@

	- strcmp(a, b) != 0
	+ !streq(a, b)

	@@
	expression a, b;
	@@

	- 0 != strcmp(a, b)
	+ !streq(a, b)

	$ find contrib/ lib* src/ -type f \
	| xargs spatch --sp-file ~/tmp/spatch/strneq.sp --in-place;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 22:23:19 -06:00
Alejandro Colomar
5581e74188 contrib/, lib/, src/: Use streq() instead of its pattern
Except for the added (and sorted) includes, and the removal of redundant
parentheses, this patch can be approximated with the following semantic
patch:

	$ cat ~/tmp/spatch/streq.sp;
	@@
	expression a, b;
	@@

	- strcmp(a, b) == 0
	+ streq(a, b)

	@@
	expression a, b;
	@@

	- 0 == strcmp(a, b)
	+ streq(a, b)

	@@
	expression a, b;
	@@

	- !strcmp(a, b)
	+ streq(a, b)

	$ find contrib/ lib* src/ -type f \
	| xargs spatch --sp-file ~/tmp/spatch/streq.sp --in-place;
	$ git restore lib/string/strcmp/streq.h;

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 22:23:19 -06:00
Alejandro Colomar
212ef97449 lib/gshadow_.h: __STDC__ is always 1
We require C11 since a long time ago.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 22:04:24 -06:00
Alejandro Colomar
1d6456542c lib/csrand.c: csrand(): Use read(2) instead of fread(2)
We don't need the heavy stdio for getting a few bytes from
</dev/urandom>.  Let's use the simpler POSIX API.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-12-01 21:43:25 -06:00
Tobias Stoeckmann
929e61d604 lib/idmapping.c: Fix get_map_ranges range check
The get_map_ranges function shall support the whole accepted range
as specified in user_namespaces(7), i.e. upper and lower from 0 to
UINT_MAX - 1 as well as range from 1 to UINT_MAX. The actual limit of
range depends on values of upper and lower and adding the range
to either upper or lower shall never overflow UINT_MAX.

Fixes: 7c43eb2c4e (2024-07-11, "lib/idmapping.c: get_map_ranges(): Move range check to a2ul() call")
Fixes: ff2baed5db (2016-08-14, "idmapping: add more checks for overflow")
Fixes: 94da3dc5c8 (2016-08-14, "also check upper for wrap")
Fixes: 7f5a14817d (2016-07-31, "get_map_ranges: check for overflow")
Co-authored-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-13 18:17:03 +01:00
Alejandro Colomar
0b8c0c893c lib/, src/: Use NULL instead of 0 as a null pointer constant
GCC 15 will add -Wzero-as-null-pointer-constant for deprecating it,
and I'm working on a paper for deprecating it from ISO C too.
Let's remove any uses in our code base.

I've done this change by building GCC from master, adding
-Werror=zero-as-null-pointer-constant to ./autogen.sh, and fixing every
error that showed up.

Closes: <https://github.com/shadow-maint/shadow/issues/1120>
Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117059>
Link: <https://software.codidact.com/posts/292718/292759#answer-292759>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-13 09:44:54 -06:00
Alejandro Colomar
8296e62957 lib/shadow.c: my_sgetspent(): There can be only one!
We already have sgetspent(), with identical semantics, defined in
<lib/sgetspent.c>.

	$ diff -u <(grepc sgetspent .) <(grepc my_sgetspent .)
	--- /dev/fd/63	2024-11-11 11:56:55.444055921 +0100
	+++ /dev/fd/62	2024-11-11 11:56:55.444055921 +0100
	@@ -1,23 +1,19 @@
	-./lib/sgetspent.c:struct spwd *
	-sgetspent(const char *string)
	+./lib/shadow.c:static struct spwd *my_sgetspent (const char *string)
	 {
	-	static char spwbuf[PASSWD_ENTRY_MAX_LENGTH];
	-	static struct spwd spwd;
	-	char *fields[FIELDS];
	-	char *cp;
	-	int i;
	+	int                 i;
	+	char                *fields[FIELDS];
	+	char                *cp;
	+	static char         spwbuf[BUFSIZ];
	+	static char         empty[] = "";
	+	static struct spwd  spwd;

		/*
		 * Copy string to local buffer.  It has to be tokenized and we
		 * have to do that to our private copy.
		 */

	-	if (strlen (string) >= sizeof spwbuf) {
	-		fprintf (shadow_logfd,
	-		         "%s: Too long passwd entry encountered, file corruption?\n",
	-		         shadow_progname);
	-		return NULL;	/* fail if too long */
	-	}
	+	if (strlen (string) >= sizeof spwbuf)
	+		return 0;
		strcpy (spwbuf, string);
		stpsep(spwbuf, "\n");

	@@ -30,14 +26,16 @@
			fields[i] = strsep(&cp, ":");

		if (i == (FIELDS - 1))
	-		fields[i++] = "";
	+		fields[i++] = empty;

		if (cp != NULL || (i != FIELDS && i != OFIELDS))
	-		return NULL;
	+		return 0;

		/*
		 * Start populating the structure.  The fields are all in
	-	 * static storage, as is the structure we pass back.
	+	 * static storage, as is the structure we pass back.  If we
	+	 * ever see a name with '+' as the first character, we try
	+	 * to turn on NIS processing.
		 */

		spwd.sp_namp = fields[0];
	@@ -46,13 +44,13 @@
		/*
		 * Get the last changed date.  For all of the integer fields,
		 * we check for proper format.  It is an error to have an
	-	 * incorrectly formatted number.
	+	 * incorrectly formatted number, unless we are using NIS.
		 */

		if (fields[2][0] == '\0')
			spwd.sp_lstchg = -1;
		else if (a2sl(&spwd.sp_lstchg, fields[2], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the minimum period between password changes.
	@@ -61,7 +59,7 @@
		if (fields[3][0] == '\0')
			spwd.sp_min = -1;
		else if (a2sl(&spwd.sp_min, fields[3], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the maximum number of days a password is valid.
	@@ -70,7 +68,7 @@
		if (fields[4][0] == '\0')
			spwd.sp_max = -1;
		else if (a2sl(&spwd.sp_max, fields[4], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * If there are only OFIELDS fields (this is a SVR3.2 /etc/shadow
	@@ -93,7 +91,7 @@
		if (fields[5][0] == '\0')
			spwd.sp_warn = -1;
		else if (a2sl(&spwd.sp_warn, fields[5], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the number of days of inactivity before an account is
	@@ -103,7 +101,7 @@
		if (fields[6][0] == '\0')
			spwd.sp_inact = -1;
		else if (a2sl(&spwd.sp_inact, fields[6], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * Get the number of days after the epoch before the account is
	@@ -113,7 +111,7 @@
		if (fields[7][0] == '\0')
			spwd.sp_expire = -1;
		else if (a2sl(&spwd.sp_expire, fields[7], NULL, 0, 0, LONG_MAX) == -1)
	-		return NULL;
	+		return 0;

		/*
		 * This field is reserved for future use.  But it isn't supposed
	@@ -123,8 +121,7 @@
		if (fields[8][0] == '\0')
			spwd.sp_flag = SHADOW_SP_FLAG_UNSET;
		else if (str2ul(&spwd.sp_flag, fields[8]) == -1)
	-		return NULL;
	+		return 0;

		return (&spwd);
	 }
	-./lib/prototypes.h:extern struct spwd *sgetspent (const char *string);

Closes: <https://github.com/shadow-maint/shadow/issues/1114>
Link: <https://www.youtube.com/watch?v=IpbvtSQvgWM>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-11 16:47:57 -06:00
Alejandro Colomar
9d8145acfc lib/gshadow.c: endsgent(): Invert logic to reduce indentation
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:11:43 -06:00
Alejandro Colomar
99a3ca17df lib/list.c: comma_to_list(): Use strchrcnt() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:07:19 -06:00
Alejandro Colomar
9efce1ac85 lib/string/strchr/: strchrcnt(): Add function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:07:19 -06:00
Alejandro Colomar
67c42427a0 lib/string/strcmp/: streq(): Add function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-10 23:07:19 -06:00
Alejandro Colomar
86451e374b lib/fs/readlink/areadlink.h: areadlink(): Use PATH_MAX instead of a magic value
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
ed569088cc lib/fs/readlink/areadlink.h: Cosmetic changes
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
32f10c3dec lib/fs/readlink/, lib/: areadlink(): Move and rename function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
f8c7955bbb lib/: Use READLINKNUL() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
5d5ab18890 lib/: Use readlinknul() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
d78d1c2fd7 lib/fs/readlink/readlinknul.h: READLINKNUL(): Add macro
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
419ce14b6f lib/fs/readlink/: readlinknul(): Add function
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-11-01 21:25:50 -05:00
Alejandro Colomar
6266a916c2 lib/loginprompt.c: login_prompt(): Use strtcpy() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-30 21:52:21 -05:00
Alejandro Colomar
3daf3f0cc4 lib/getdef.c: Remove dead code
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-30 21:15:30 -05:00
Alejandro Colomar
0589cbc135 lib/fields.c: Remove dead code
A few lines above, we've removed the '\n' already.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-30 21:15:30 -05:00
Alejandro Colomar
afc4b574b7 lib/alloc/realloc*.h: Always reallocate at least 1 byte
glibc's realloc(3) is broken.  It was originally good (I believe) until
at some point, when it was changed to conform to C89, which had a bogus
specification that required that it returns NULL.  C99 fixed the mistake
from C89, and so glibc's realloc(3) is non-conforming to
C99/C11/POSIX.1-2008.  C17 broke again the definition of realloc(3).

Link: <https://github.com/shadow-maint/shadow/pull/1095>
Link: <https://nabijaczleweli.xyz/content/blogn_t/017-malloc0.html>
Link: <https://inbox.sourceware.org/libc-alpha/5gclfbrxfd7446gtwd2x2gfuquy7ukjdbrndphyfmfszxlft76@wwjz7spd4vd7/T/#t>
Co-developed-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Acked-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-22 10:53:06 +02:00
Alejandro Colomar
12aa29b576 lib/alloc/realloc*.h: Rename macro parameter
This is in preparation for the following commit, which will need this
shorter parameter name to avoid breaking long lines.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-22 10:53:06 +02:00
Alejandro Colomar
276f3fde26 lib/gshadow.c: endsgent(): Remove dead assignment
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Alejandro Colomar
02d4af7f6f lib/port.c: portcmp(): Use strcmp(3) instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Alejandro Colomar
f45adadd28 lib/, src/: Use stpspn() instead of its pattern
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-10-13 20:40:02 -05:00
Tobias Stoeckmann
e6a5484ced lib: Eliminate dead code
The tz function is only called if ENV_TZ starts with a slash.

If the specified file cannot be read, the code implies that ENV_TZ
would be returned if it does not start with a slash.

Since we know that it DOES start with a slash, the code can be
simplified to state that "TZ=CST6CDT" is returned as a default if
the specified file cannot be read.

Benefit of this change is that strcpy's use case here can be
easier verified.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-29 12:23:05 +02:00
Tobias Stoeckmann
dd6cddd481 lib/run_part: Adjust style
Remove some of these whitespaces.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00
Tobias Stoeckmann
76c97ed7ec lib/run_part: Unify error messages
At least if they can be assigned directly to a function call.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00
Tobias Stoeckmann
62bd261fbe lib: Fix typo
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2024-09-18 14:52:05 +02:00