Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-24 Thread Andreas Schwab
On Mär 24 2021, Heinrich Schuchardt wrote:

> And foo is obviously "changed  between the setjmp invocation and longjmp
> call".
>
> The current version of the patch is:
> https://patchwork.ozlabs.org/project/uboot/patch/20210323181127.32411-3-xypron.g...@gmx.de/
>
> So I guess we have to declare env as volatile in setjmp() in this
> version of the patch because it is changed between the setjmp and
> longjmp invocations?

Yes, I think so, or make it static.

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-24 Thread Heinrich Schuchardt
On 24.03.21 13:39, Andreas Schwab wrote:
> On Mär 24 2021, Heinrich Schuchardt wrote:
>
>> And foo is obviously "changed  between the setjmp invocation and longjmp
>> call".
>>
>> The current version of the patch is:
>> https://patchwork.ozlabs.org/project/uboot/patch/20210323181127.32411-3-xypron.g...@gmx.de/
>>
>> So I guess we have to declare env as volatile in setjmp() in this
>> version of the patch because it is changed between the setjmp and
>> longjmp invocations?
>
> Yes, I think so, or make it static.

The whole point of this variable during test is that it lives on the
stack. So static is not what I am looking for.

Actually adding volatile does not change the generated machine code
because test_longjmp() is marked as noinline and therefore has its own
stack frame separated from test_setjmp().

But adding volatile adds to the portability. So I will respin the series.

Best regards

Heinrich


Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-24 Thread Andreas Schwab
On Mär 22 2021, Sean Anderson wrote:

> int test_longjmp_ret(int i)
> {
>  jmp_buf env;
>  int ret;
>  int foo = i;
>
>  ret = setjmp(env);
>  if (ret)
>  return foo;
>  foo = 0x1000;
>  longjmp(env, i);
>  /* We should not arrive here */
>  return foo;

This is undefined.  When modifying a non-volatile auto variable between
setjmp and longjmp, there is no requirement that the value is preserved.

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-24 Thread Heinrich Schuchardt
On 24.03.21 10:18, Andreas Schwab wrote:
> On Mär 22 2021, Sean Anderson wrote:
>
>> int test_longjmp_ret(int i)
>> {
>>  jmp_buf env;
>>  int ret;
>>  int foo = i;
>>
>>  ret = setjmp(env);
>>  if (ret)
>>  return foo;
>>  foo = 0x1000;
>>  longjmp(env, i);
>>  /* We should not arrive here */
>>  return foo;
>
> This is undefined.  When modifying a non-volatile auto variable between
> setjmp and longjmp, there is no requirement that the value is preserved.
>
> Andreas.
>

Hello Andreas,

thank you for reviewing.

Your comment relates to the following paragraph in the C99 specification:

"All  accessible  objects  have  values,  and  all  other  components
of the  abstract  machine have  state,  as  of  the  time  the longjmp
function  was  called,  except  that  the  values  of objects  of
automatic  storage  duration  that  are  local  to  the  function
containing  the invocation  of  the  corresponding setjmp macro  that
do  not  have  volatile-qualified  type and  have  been  changed
between the setjmp invocation and longjmp call are indeterminate."

And foo is obviously "changed  between the setjmp invocation and longjmp
call".

The current version of the patch is:
https://patchwork.ozlabs.org/project/uboot/patch/20210323181127.32411-3-xypron.g...@gmx.de/

So I guess we have to declare env as volatile in setjmp() in this
version of the patch because it is changed between the setjmp and
longjmp invocations?

Best regards

Heinrich




Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-23 Thread Sean Anderson

On 3/22/21 12:42 PM, Heinrich Schuchardt wrote:

On 22.03.21 14:30, Sean Anderson wrote:


On 3/22/21 9:23 AM, Sean Anderson wrote:


On 3/22/21 7:02 AM, Heinrich Schuchardt wrote:

Provide a unit test for the longjmp() library function

Signed-off-by: Heinrich Schuchardt 
---
v2:
     no change
---
   test/lib/Makefile  |  1 +
   test/lib/longjmp.c | 44 
   2 files changed, 45 insertions(+)
   create mode 100644 test/lib/longjmp.c

diff --git a/test/lib/Makefile b/test/lib/Makefile
index 97c11e35a8..a30f615aa9 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
   obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
   obj-y += hexdump.o
   obj-y += lmb.o
+obj-y += longjmp.o
   obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
   obj-$(CONFIG_SSCANF) += sscanf.o
   obj-y += string.o
diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c
new file mode 100644
index 00..7571540ffc
--- /dev/null
+++ b/test/lib/longjmp.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test setjmp(), longjmp()
+ *
+ * Copyright (c) 2021, Heinrich Schuchardt 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * test_longjmp_ret() - get longjmp() return value
+ *
+ * @i:    value passed to longjmp()
+ * Return:    value returned by longjmp()
+ */
+int test_longjmp_ret(int i)
+{
+    jmp_buf env;
+    int ret;
+
+    ret = setjmp(env);
+    if (ret)
+    return ret;
+    longjmp(env, i);
+    /* We should not arrive here */
+    return 0x1000;
+}
+
+static int lib_test_longjmp(struct unit_test_state *uts)
+{
+    int i;
+
+    for (i = -3; i < 0; ++i)
+    ut_asserteq(i, test_longjmp_ret(i));
+    ut_asserteq(1, test_longjmp_ret(0));
+    for (i = 1; i < 4; ++i)
+    ut_asserteq(i, test_longjmp_ret(i));
+    return 0;
+}
+LIB_TEST(lib_test_longjmp, 0);
--
2.30.2



Reviewed-by: Sean Anderson 
Tested-by: Sean Anderson 

Though I would like to test that variables are set correctly e.g. by
doing

int test_longjmp_ret(int i)
{
  jmp_buf env;
  int ret;

  ret = setjmp(env);
  if (ret)
  return ret;
  ret = 0x1000;
  longjmp(env, i);
  /* We should not arrive here */
  return ret;
}

--Sean


err, rather by doing

int test_longjmp_ret(int i)
{
  jmp_buf env;
  int ret;
  int foo = i;

  ret = setjmp(env);
  if (ret)
  return foo;
  foo = 0x1000;
  longjmp(env, i);
  /* We should not arrive here */
  return foo;
}

or something else which demonstrates that variables get reset to their
earlier values.

--Sean


Hello Sean,

thank you for reviewing.

Would the following make sense to you to check that the stack pointer is
correctly restored?


struct test_jmp_buf {
 jmp_buf env;
 int val;
};

/**
  * test_longjmp() - test longjmp function
  *
  * @i is passed to longjmp.
  * @i << 8 is set in the environment structure.
  *
  * @env:environment
  * @i:  value passed to longjmp()
  */
static void noinline test_longjmp(struct test_jmp_buf *env, int i)
{
 env->val = i << 8;
 longjmp(env->env, i);
}

/**
  * test_setjmp() - test setjmp function
  *
  * setjmp() will return the value @i passed to longjmp() if @i is non-zero.
  * For @i == 0 we expect return value 1.
  *
  * @i << 8 will be set by test_longjmp in the environment structure.
  * This value can be used to check that the stack frame is restored.
  *
  * We return the XORed values to allow simply check both at once.
  *
  * @i:  value passed to longjmp()
  * Return:  values return byby longjmp()


nit: by


  */
static int test_setjmp(int i)
{
 struct test_jmp_buf env;
 int ret;

 env.val = -1;
 ret = setjmp(env.env);
 if (ret)
 return ret ^ env.val;
 test_longjmp(, i);
 /* We should not arrive here */
 return 0x1000;
}

Best regards

Heinrich



Yes, this looks good.

--Sean



Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-22 Thread Heinrich Schuchardt
On 22.03.21 14:30, Sean Anderson wrote:
>
> On 3/22/21 9:23 AM, Sean Anderson wrote:
>>
>> On 3/22/21 7:02 AM, Heinrich Schuchardt wrote:
>>> Provide a unit test for the longjmp() library function
>>>
>>> Signed-off-by: Heinrich Schuchardt 
>>> ---
>>> v2:
>>>     no change
>>> ---
>>>   test/lib/Makefile  |  1 +
>>>   test/lib/longjmp.c | 44 
>>>   2 files changed, 45 insertions(+)
>>>   create mode 100644 test/lib/longjmp.c
>>>
>>> diff --git a/test/lib/Makefile b/test/lib/Makefile
>>> index 97c11e35a8..a30f615aa9 100644
>>> --- a/test/lib/Makefile
>>> +++ b/test/lib/Makefile
>>> @@ -7,6 +7,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
>>>   obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
>>>   obj-y += hexdump.o
>>>   obj-y += lmb.o
>>> +obj-y += longjmp.o
>>>   obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
>>>   obj-$(CONFIG_SSCANF) += sscanf.o
>>>   obj-y += string.o
>>> diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c
>>> new file mode 100644
>>> index 00..7571540ffc
>>> --- /dev/null
>>> +++ b/test/lib/longjmp.c
>>> @@ -0,0 +1,44 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Test setjmp(), longjmp()
>>> + *
>>> + * Copyright (c) 2021, Heinrich Schuchardt 
>>> + */
>>> +
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +
>>> +/**
>>> + * test_longjmp_ret() - get longjmp() return value
>>> + *
>>> + * @i:    value passed to longjmp()
>>> + * Return:    value returned by longjmp()
>>> + */
>>> +int test_longjmp_ret(int i)
>>> +{
>>> +    jmp_buf env;
>>> +    int ret;
>>> +
>>> +    ret = setjmp(env);
>>> +    if (ret)
>>> +    return ret;
>>> +    longjmp(env, i);
>>> +    /* We should not arrive here */
>>> +    return 0x1000;
>>> +}
>>> +
>>> +static int lib_test_longjmp(struct unit_test_state *uts)
>>> +{
>>> +    int i;
>>> +
>>> +    for (i = -3; i < 0; ++i)
>>> +    ut_asserteq(i, test_longjmp_ret(i));
>>> +    ut_asserteq(1, test_longjmp_ret(0));
>>> +    for (i = 1; i < 4; ++i)
>>> +    ut_asserteq(i, test_longjmp_ret(i));
>>> +    return 0;
>>> +}
>>> +LIB_TEST(lib_test_longjmp, 0);
>>> -- 
>>> 2.30.2
>>>
>>
>> Reviewed-by: Sean Anderson 
>> Tested-by: Sean Anderson 
>>
>> Though I would like to test that variables are set correctly e.g. by
>> doing
>>
>> int test_longjmp_ret(int i)
>> {
>>  jmp_buf env;
>>  int ret;
>>
>>  ret = setjmp(env);
>>  if (ret)
>>  return ret;
>>  ret = 0x1000;
>>  longjmp(env, i);
>>  /* We should not arrive here */
>>  return ret;
>> }
>>
>> --Sean
>
> err, rather by doing
>
> int test_longjmp_ret(int i)
> {
>  jmp_buf env;
>  int ret;
>  int foo = i;
>
>  ret = setjmp(env);
>  if (ret)
>  return foo;
>  foo = 0x1000;
>  longjmp(env, i);
>  /* We should not arrive here */
>  return foo;
> }
>
> or something else which demonstrates that variables get reset to their
> earlier values.
>
> --Sean

Hello Sean,

thank you for reviewing.

Would the following make sense to you to check that the stack pointer is
correctly restored?


struct test_jmp_buf {
jmp_buf env;
int val;
};

/**
 * test_longjmp() - test longjmp function
 *
 * @i is passed to longjmp.
 * @i << 8 is set in the environment structure.
 *
 * @env:environment
 * @i:  value passed to longjmp()
 */
static void noinline test_longjmp(struct test_jmp_buf *env, int i)
{
env->val = i << 8;
longjmp(env->env, i);
}

/**
 * test_setjmp() - test setjmp function
 *
 * setjmp() will return the value @i passed to longjmp() if @i is non-zero.
 * For @i == 0 we expect return value 1.
 *
 * @i << 8 will be set by test_longjmp in the environment structure.
 * This value can be used to check that the stack frame is restored.
 *
 * We return the XORed values to allow simply check both at once.
 *
 * @i:  value passed to longjmp()
 * Return:  values return byby longjmp()
 */
static int test_setjmp(int i)
{
struct test_jmp_buf env;
int ret;

env.val = -1;
ret = setjmp(env.env);
if (ret)
return ret ^ env.val;
test_longjmp(, i);
/* We should not arrive here */
return 0x1000;
}

Best regards

Heinrich


Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-22 Thread Sean Anderson



On 3/22/21 9:23 AM, Sean Anderson wrote:


On 3/22/21 7:02 AM, Heinrich Schuchardt wrote:

Provide a unit test for the longjmp() library function

Signed-off-by: Heinrich Schuchardt 
---
v2:
no change
---
  test/lib/Makefile  |  1 +
  test/lib/longjmp.c | 44 
  2 files changed, 45 insertions(+)
  create mode 100644 test/lib/longjmp.c

diff --git a/test/lib/Makefile b/test/lib/Makefile
index 97c11e35a8..a30f615aa9 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
  obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
  obj-y += hexdump.o
  obj-y += lmb.o
+obj-y += longjmp.o
  obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
  obj-$(CONFIG_SSCANF) += sscanf.o
  obj-y += string.o
diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c
new file mode 100644
index 00..7571540ffc
--- /dev/null
+++ b/test/lib/longjmp.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test setjmp(), longjmp()
+ *
+ * Copyright (c) 2021, Heinrich Schuchardt 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * test_longjmp_ret() - get longjmp() return value
+ *
+ * @i:value passed to longjmp()
+ * Return:value returned by longjmp()
+ */
+int test_longjmp_ret(int i)
+{
+jmp_buf env;
+int ret;
+
+ret = setjmp(env);
+if (ret)
+return ret;
+longjmp(env, i);
+/* We should not arrive here */
+return 0x1000;
+}
+
+static int lib_test_longjmp(struct unit_test_state *uts)
+{
+int i;
+
+for (i = -3; i < 0; ++i)
+ut_asserteq(i, test_longjmp_ret(i));
+ut_asserteq(1, test_longjmp_ret(0));
+for (i = 1; i < 4; ++i)
+ut_asserteq(i, test_longjmp_ret(i));
+return 0;
+}
+LIB_TEST(lib_test_longjmp, 0);
--
2.30.2



Reviewed-by: Sean Anderson 
Tested-by: Sean Anderson 

Though I would like to test that variables are set correctly e.g. by doing

int test_longjmp_ret(int i)
{
 jmp_buf env;
 int ret;

 ret = setjmp(env);
 if (ret)
 return ret;
 ret = 0x1000;
 longjmp(env, i);
 /* We should not arrive here */
 return ret;
}

--Sean


err, rather by doing

int test_longjmp_ret(int i)
{
 jmp_buf env;
 int ret;
 int foo = i;

 ret = setjmp(env);
 if (ret)
 return foo;
 foo = 0x1000;
 longjmp(env, i);
 /* We should not arrive here */
 return foo;
}

or something else which demonstrates that variables get reset to their
earlier values.

--Sean


Re: [PATCH v2 2/2] test: unit test for longjmp

2021-03-22 Thread Sean Anderson



On 3/22/21 7:02 AM, Heinrich Schuchardt wrote:

Provide a unit test for the longjmp() library function

Signed-off-by: Heinrich Schuchardt 
---
v2:
no change
---
  test/lib/Makefile  |  1 +
  test/lib/longjmp.c | 44 
  2 files changed, 45 insertions(+)
  create mode 100644 test/lib/longjmp.c

diff --git a/test/lib/Makefile b/test/lib/Makefile
index 97c11e35a8..a30f615aa9 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
  obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
  obj-y += hexdump.o
  obj-y += lmb.o
+obj-y += longjmp.o
  obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
  obj-$(CONFIG_SSCANF) += sscanf.o
  obj-y += string.o
diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c
new file mode 100644
index 00..7571540ffc
--- /dev/null
+++ b/test/lib/longjmp.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test setjmp(), longjmp()
+ *
+ * Copyright (c) 2021, Heinrich Schuchardt 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * test_longjmp_ret() - get longjmp() return value
+ *
+ * @i: value passed to longjmp()
+ * Return: value returned by longjmp()
+ */
+int test_longjmp_ret(int i)
+{
+   jmp_buf env;
+   int ret;
+
+   ret = setjmp(env);
+   if (ret)
+   return ret;
+   longjmp(env, i);
+   /* We should not arrive here */
+   return 0x1000;
+}
+
+static int lib_test_longjmp(struct unit_test_state *uts)
+{
+   int i;
+
+   for (i = -3; i < 0; ++i)
+   ut_asserteq(i, test_longjmp_ret(i));
+   ut_asserteq(1, test_longjmp_ret(0));
+   for (i = 1; i < 4; ++i)
+   ut_asserteq(i, test_longjmp_ret(i));
+   return 0;
+}
+LIB_TEST(lib_test_longjmp, 0);
--
2.30.2



Reviewed-by: Sean Anderson 
Tested-by: Sean Anderson 

Though I would like to test that variables are set correctly e.g. by doing

int test_longjmp_ret(int i)
{
jmp_buf env;
int ret;

ret = setjmp(env);
if (ret)
return ret;
ret = 0x1000;
longjmp(env, i);
/* We should not arrive here */
return ret;
}

--Sean


[PATCH v2 2/2] test: unit test for longjmp

2021-03-22 Thread Heinrich Schuchardt
Provide a unit test for the longjmp() library function

Signed-off-by: Heinrich Schuchardt 
---
v2:
no change
---
 test/lib/Makefile  |  1 +
 test/lib/longjmp.c | 44 
 2 files changed, 45 insertions(+)
 create mode 100644 test/lib/longjmp.c

diff --git a/test/lib/Makefile b/test/lib/Makefile
index 97c11e35a8..a30f615aa9 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_EFI_LOADER) += efi_device_path.o
 obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o
 obj-y += hexdump.o
 obj-y += lmb.o
+obj-y += longjmp.o
 obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
 obj-$(CONFIG_SSCANF) += sscanf.o
 obj-y += string.o
diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c
new file mode 100644
index 00..7571540ffc
--- /dev/null
+++ b/test/lib/longjmp.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test setjmp(), longjmp()
+ *
+ * Copyright (c) 2021, Heinrich Schuchardt 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * test_longjmp_ret() - get longjmp() return value
+ *
+ * @i: value passed to longjmp()
+ * Return: value returned by longjmp()
+ */
+int test_longjmp_ret(int i)
+{
+   jmp_buf env;
+   int ret;
+
+   ret = setjmp(env);
+   if (ret)
+   return ret;
+   longjmp(env, i);
+   /* We should not arrive here */
+   return 0x1000;
+}
+
+static int lib_test_longjmp(struct unit_test_state *uts)
+{
+   int i;
+
+   for (i = -3; i < 0; ++i)
+   ut_asserteq(i, test_longjmp_ret(i));
+   ut_asserteq(1, test_longjmp_ret(0));
+   for (i = 1; i < 4; ++i)
+   ut_asserteq(i, test_longjmp_ret(i));
+   return 0;
+}
+LIB_TEST(lib_test_longjmp, 0);
--
2.30.2