From 48f052b29333a2c65ba16147b82a45cf81f22a90 Mon Sep 17 00:00:00 2001
From: Andre Maroneze <andre.maroneze@cea.fr>
Date: Thu, 24 Mar 2022 08:01:47 +0100
Subject: [PATCH] [Libc] improve spec of read

---
 share/libc/unistd.h   | 16 ++++++++++++++--
 tests/libc/unistd_h.c | 16 +++++++++++++---
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/share/libc/unistd.h b/share/libc/unistd.h
index f26a5b8ed9b..4842b7958b5 100644
--- a/share/libc/unistd.h
+++ b/share/libc/unistd.h
@@ -1009,8 +1009,20 @@ extern ssize_t      pwrite(int, const void *, size_t, off_t);
   assigns __fc_fds[fd] \from __fc_fds[fd];
   assigns \result, *((char *)buf+(0..count-1))
           \from indirect:__fc_fds[fd], indirect:count;
-  ensures  result_error_or_read_length: 0 <= \result <= count || \result == -1;
-  ensures  initialization:buf: \initialized(((char*)buf)+(0..\result-1));
+  behavior full_read:
+    assumes nondet_small_count: Frama_C_entropy_source && count <= SSIZE_MAX;
+    ensures res_full: \result == count;
+    ensures res_init:initialization: \initialized(((char*)buf)+(0..count-1));
+  behavior large_read_implementation_defined:
+    assumes nondet_large_count: Frama_C_entropy_source && count > SSIZE_MAX;
+    ensures res_init:initialization: \initialized(((char*)buf)+(0..count-1));
+  behavior partial_or_error:
+    assumes nondet: !Frama_C_entropy_source;
+    ensures result_error_or_read_length: -1 <= \result < count;
+    ensures initialization:buf: \initialized(((char*)buf)+(0..\result-1));
+            //note: for \result == -1, the above range is empty, as intended
+  disjoint behaviors;
+  complete behaviors;
 */
 extern ssize_t      read(int fd, void *buf, size_t count);
 
diff --git a/tests/libc/unistd_h.c b/tests/libc/unistd_h.c
index 5bb417437e2..a8b8dbba169 100644
--- a/tests/libc/unistd_h.c
+++ b/tests/libc/unistd_h.c
@@ -1,11 +1,11 @@
 /*run.config
-  STDOPT: #"-eva-slevel 12" #"-eva-split-return auto"
-  STDOPT: #"-variadic-no-translation" #"-eva-slevel 12" #"-eva-split-return auto"
+  STDOPT: #"-machdep x86_32 -eva-slevel 12" #"-eva-split-return auto"
+  STDOPT: #"-machdep x86_32 -variadic-no-translation" #"-eva-slevel 12" #"-eva-split-return auto"
 */
 #define _GNU_SOURCE
 #define _XOPEN_SOURCE 600
 #include <unistd.h>
-
+#include <stdint.h>
 volatile int nondet;
 
 int main() {
@@ -107,5 +107,15 @@ int main() {
   int unslept = sleep(42);
   //@ assert 0 <= unslept <= 42;
 
+  char buf[SIZE_MAX];
+  ssize_t rread = read(fd, buf, 32);
+  if (rread == 32) {
+    //@ assert \initialized(buf+(0..31));
+  }
+  if (rread == -1)
+  // In x86-32, SSIZE_MAX < SIZE_MAX, so we check for issues
+  rread = read(fd, buf, SSIZE_MAX);
+  rread = read(fd, buf, SIZE_MAX);
+
   return 0;
 }
-- 
GitLab