temporal verification as a program analysis taskejk/slides/cav11.pdftemporal verification as a...
TRANSCRIPT
Temporal verification as a program analysis task
CAV 201119 July 2011
Moshe VardiRice University
Eric KoskinenUniversity of Cambridge
Byron CookMicrosoft Research
Queen Mary, London
Monday, February 13, 2012
Prove temporal properties of real programs
Monday, February 13, 2012
POPL ’11
Prove temporal properties of real programs
Trace-based properties can be provedusing state-based techniques viaiterated symbolic determinization
Monday, February 13, 2012
POPL ’11
Prove temporal properties of real programs
Trace-based properties can be provedusing state-based techniques viaiterated symbolic determinization
CAV ’11
Efficient state-basedtemporal verification technique
Monday, February 13, 2012
POPL ’11
Prove temporal properties of real programs
Trace-based properties can be provedusing state-based techniques viaiterated symbolic determinization
CAV ’11
Efficient state-basedtemporal verification technique
P ⊢ φ∀CTL
∀CTL proof procedure
CAV’11Monday, February 13, 2012
POPL ’11
Prove temporal properties of real programs
Trace-based properties can be provedusing state-based techniques viaiterated symbolic determinization
CAV ’11
Efficient state-basedtemporal verification technique
P ⊢ φ∀CTL
∀CTL proof procedure
CAV’11
LTL proof procedure
P ⊢ φLTL
P ⊢ φ∀CTL
POPL’11
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Proving this statically is challenging.Reason about termination.Reason about reachability.
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Previous technique
Proving this statically is challenging.Reason about termination.Reason about reachability.
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Previous techniquetimeout
Proving this statically is challenging.Reason about termination.Reason about reachability.
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Previous techniquetimeout
Proving this statically is challenging.Reason about termination.Reason about reachability.
(AF error) ∨ AF (added>0 ∧ AF ret=OK)
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
Previous techniquetimeout
Our technique
Proving this statically is challenging.Reason about termination.Reason about reachability.
(AF error) ∨ AF (added>0 ∧ AF ret=OK)
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
✔
Previous techniquetimeout
Our technique
Proving this statically is challenging.Reason about termination.Reason about reachability.
(AF error) ∨ AF (added>0 ∧ AF ret=OK)
Monday, February 13, 2012
/* * StreamServerPort -- open a "listening" port to accept connections. * * Successfully opened sockets are added to the ListenSocket[] array, * at the first position that isn't -1. * * RETURNS: STATUS_OK or STATUS_ERROR */
intStreamServerPort(int family, char *hostName, unsigned short portNumber, char *unixSocketName, int ListenSocket[], int MaxListen)void body(){ /* Initialize hint structure */
#ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { /* Lock_AF_UNIX will also fill in sock_path. */ /* if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK) */ /* return STATUS_ERROR; */ service = sock_path; } else#endif /* HAVE_UNIX_SOCKETS */ { snprintf(1, sizeof(1), "%d", portNumber); service = 1; }
ret = getaddrinfo_all(hostName, service, &hint, &addrs); if (ret || !addrs) {! if (hostName) { /* ereport(LOG, */ /* (errmsg("could not translate host name \"%s\", service \"%s\" to address: %s", */ /* hostName, service, gai_strerror(ret)))); */! } else { /* ereport(LOG, */ /* (errmsg("could not translate service \"%s\" to address: %s", */ /* service, gai_strerror(ret)))); */ /* if (addrs) */ /* freeaddrinfo_all(hint.ai_family, addrs); */! } return STATUS_ERROR; }
for (addr = addrs; addr < MAXADDR; addr++) // = addr->ai_next) { if (!IS_AF_UNIX(family) && IS_AF_UNIX(addr_ai_family)) { /* * Only set up a unix domain socket when they really asked for * it. The service/port is different in that case. */ continue; }
/* See if there is still room to add 1 more socket. */ for (; listen_index < MaxListen; listen_index++) { if (ListenSocket_OF_listen_index == -1) break; } if (listen_index >= MaxListen) { /* ereport(LOG, */ /* (errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded", */ /* MaxListen))); */ break; }
/* set up family name for possible error messages */ switch (addr_ai_family) { case AF_INET: gettext("IPv4"); break;#ifdef HAVE_IPV6 case AF_INET6: gettext("IPv6"); break;#endif#ifdef HAVE_UNIX_SOCKETS case AF_UNIX: gettext("Unix"); break;#endif default:! ! ! snprintf(1,/*familyDescBuf*/ sizeof(familyDescBuf), gettext("unrecognized address family %d"), addr_ai_family); //familyDesc = familyDescBuf; break; }
if ((fd = nondet())) // socket(addr_ai_family, SOCK_STREAM, 0)) < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not create %s socket: %m", */ /* familyDesc))); */ continue; }
if (nondet()) // !IS_AF_UNIX(addr_ai_family)) {! ! if (nondet()) //(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,! ! // (char *) &one, sizeof(one))) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); */ /* closesocket(fd); */ continue; } }
#ifdef IPV6_V6ONLY if (nondet()) // addr_ai_family == AF_INET6) {! ! if (nondet()) // setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,! ! // (char *) &one, sizeof(one)) == -1) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); */ closesocket(fd); continue; } }#endif
/* * Note: This might fail on some OS's, like Linux older than * 2.4.21-pre3, that don't have the IPV6_V6ONLY socket option, and * map ipv4 addresses to ipv6. It will show ::ffff:ipv4 for all * ipv4 connections. */ err = nondet(); // bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { /* ereport(LOG, */ /* (errcode_for_socket_access(), */ /* /\* translator: %s is IPv4, IPv6, or Unix *\/ */ /* errmsg("could not bind %s socket: %m", */ /* familyDesc), */ /* (IS_AF_UNIX(addr_ai_family)) ? */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, remove socket file \"%s\" and retry.", */ /* (int) portNumber, sock_path) : */ /* errhint("Is another postmaster already running on port %d?" */ /* " If not, wait a few seconds and retry.", */ /* (int) portNumber))); */ closesocket(fd); continue; }
#ifdef HAVE_UNIX_SOCKETS if (addr_ai_family == AF_UNIX) {! ! if (nondet() != STATUS_OK) { closesocket(fd); break; } }#endif
/* * Select appropriate accept-queue length limit. PG_SOMAXCONN is * only intended to provide a clamp on the request on platforms * where an overly large request provokes a kernel error (are * there any?). */ maxconn = MaxBackends * 2; if (maxconn > PG_SOMAXCONN) maxconn = PG_SOMAXCONN;
err = listen(fd, maxconn); if (err < 0) {
closesocket(fd); continue; } ListenSocket_OF_listen_index = fd; added++; }
//freeaddrinfo_all(hint.ai_family, addrs);
if (!added) { ret = STATUS_ERROR;! ! while(1) { int rrr; rrr=rrr; }! }
ret = STATUS_OK;! while(1) { int ddd; ddd=ddd; }}
(G ¬error) ⇒ F (added>0 ∧ F ret=OK)
int StreamServerPort(int family, ...)PostgreSQL StreamServer
✔9.56 s
Previous techniquetimeout
Our technique
Proving this statically is challenging.Reason about termination.Reason about reachability.
(AF error) ∨ AF (added>0 ∧ AF ret=OK)
Monday, February 13, 2012
Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
POPL’11, CAV’11Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
POPL’11, CAV’11
timeout
Monday, February 13, 2012
Example
Monday, February 13, 2012
Example
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
Monday, February 13, 2012
Example
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
φ ≡ AG(acq ⇒ AF rel)∀CTL Property
φ :=|||||
pφ ∧ φ φ ∨ φAG φAF φ...
Monday, February 13, 2012
∀CTL Property
φ :=|||||
pφ ∧ φ φ ∨ φAG φAF φ...
Example
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
What happens when you try touse them on infinite state systems?
Decades and decades of work on proving temporal logic
for finite state systems(circuits, hardware, protocols, etc.)
φ ≡ AG(acq ⇒ AF rel)
Monday, February 13, 2012
Example
(s1,acq),(s2,acq),...
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
Known Challenge
S × sub(φ)
(s1,rel),(s2,rel),...
(s1,F rel),(s2,F rel),...
φ ≡ AG(acq ⇒ AF rel)
Monday, February 13, 2012
Example
(s1,acq),(s2,acq),...
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
Known Challenge
S × sub(φ)
(s1,rel),(s2,rel),...
(s1,F rel),(s2,F rel),...
Infinitely many states
φ ≡ AG(acq ⇒ AF rel)
Monday, February 13, 2012
Example
(s1,acq),(s2,acq),...
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
Known Challenge
S × sub(φ)
(s1,rel),(s2,rel),...
(s1,F rel),(s2,F rel),...
Infinitely many statesAll existing toolsuse abstraction
φ ≡ AG(acq ⇒ AF rel)
Monday, February 13, 2012
Example
(s1,acq),(s2,acq),...
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
Known Challenge
S × sub(φ)
(s1,rel),(s2,rel),...
(s1,F rel),(s2,F rel),...
Infinitely many statesAll existing toolsuse abstraction
φ ≡ AG(acq ⇒ AF rel)
Monday, February 13, 2012
Example
(s1,acq),(s2,acq),...
assume(y>0);while(*) { acq(); while(x<y && y<z) { if * then x = x + y else z = x - y } rel();}while(1);
Known Challenge
S × sub(φ)
(s1,rel),(s2,rel),...
(s1,F rel),(s2,F rel),...
Infinitely many statesAll existing toolsuse abstraction
φ ≡ AG(acq ⇒ AF rel)
but most suffer from performance problems
Monday, February 13, 2012
Our Idea
P ⊢ φ∀CTL
∀CTL proof procedure
CAV’11
programanalysis task
(symbolic MC, AI)
Monday, February 13, 2012
Our Idea
P ⊢ φ∀CTL
∀CTL proof procedure
CAV’11
programanalysis task
(symbolic MC, AI)
These tools are good at finding the “right”
abstraction
Monday, February 13, 2012
Our Idea
P � ϕ
Monday, February 13, 2012
Our Idea
P � ϕ
new program(M)
Monday, February 13, 2012
Our Idea
P � ϕ
cannot return falsenew program(M)
Monday, February 13, 2012
Our Idea
P � ϕ
⇒cannot return falsenew program(M)
Monday, February 13, 2012
Our Idea
P � ϕ
⇒
Existing tools to show this invariant
cannot return falsenew program(M)
Monday, February 13, 2012
Our Idea
P � ϕ
⇒
Existing tools to show this invariant
∃M. cannot return false
termination argument
new program(M)
Monday, February 13, 2012
Our Idea
Existing tools to find term. argument
P � ϕ
⇒
Existing tools to show this invariant
∃M. cannot return false
termination argument
new program(M)
Monday, February 13, 2012
Our Idea
Existing tools to find term. argument
P � ϕ
⇒
Existing tools to show this invariant
∃M. cannot return false
Program analysis tools are good at finding the “right” abstraction
termination argument
new program(M)
Monday, February 13, 2012
Our Idea
Existing tools to find term. argument
⇒
Existing tools to show this invariant
∃M. cannot return false
Program analysis tools are good at finding the “right” abstraction
(S,R, I) � ϕtermination argument
new program(M)
Monday, February 13, 2012
Our Idea
⇒∃M. cannot return false
(S,R, I) � ϕ
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
Use existing program analysis tools
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
Use existing program analysis tools
Use existing termination tools
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
Use existing program analysis tools
Fast.
Use existing termination tools
AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
How does encoding work?
Monday, February 13, 2012
How does encoding work?
• Using procedures and nondeterminism ...
... encode the search for a proof (or c.e.x.)
Monday, February 13, 2012
How does encoding work?
• Using procedures and nondeterminism ...
... encode the search for a proof (or c.e.x.)
• Trick existing tools into giving you :
• Backtracking
• Eventuality checking
• Tree-based counterexamples
• Abstraction refinement at the right time
Monday, February 13, 2012
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Example
AG (n ≤ x)
x = *; n = x-1;while (*) { acq(); n = x-1; while (n>0) n--; rel();}while (1) ;
AG p
Reachability
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Example
AG (n ≤ x)
x = *; n = x-1;while (*) { acq(); n = x-1; while (n>0) n--; rel();}while (1) ;
ReachabilityAG p
Reachability
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .Example
AG (n ≤ x)
x = *; n = x-1;while (*) { acq(); n = x-1; while (n>0) n--; rel();}while (1) ;
Reachability
AG p
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .Example
AG (n ≤ x)
x = *; n = x-1;while (*) { acq(); n = x-1; while (n>0) n--; rel();}while (1) ;
Reachability
AG p
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .Example
AG (n ≤ x)
x = *; n = x-1;while (*) { acq(); n = x-1; while (n>0) n--; rel();}while (1) ;
Reachability
AG p
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .Example
AG (n ≤ x)
x = *; n = x-1;while (*) { acq(); n = x-1; while (n>0) n--; rel();}while (1) ;
Reachability
AG p
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .
Reachability
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .
Reachability
noop, effectively
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .
Reachability
noop, effectively
check subprop
Monday, February 13, 2012
∃M. ∀s ∈ I. E(�s,ϕ�,M, R) c.r. false P � ϕ⇒
. . .
. . .
Q . . .
Reachability
noop, effectively
check subprop
step in program
Monday, February 13, 2012
AF p
Eventuality
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
TerminationAF p
Eventuality
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
AF p
Eventuality
Example
x = *; y = *; z = *;if (y>0) { while(x<y && y<z){ if (*) x = x + y else z = x - y }}l: p=1;
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
AF p
Eventuality
Example
x = *; y = *; z = *;if (y>0) { while(x<y && y<z){ if (*) x = x + y else z = x - y }}l: p=1;
} This loopterminates
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Termination Argument:T(s,t) =
t(y) < t(z) ⋀ t(z) ≤ s(z) − 1⋁
t(x) < t(y) ⋀ t(x) ≥ s(x) + 1
AF p
Eventuality
Example
x = *; y = *; z = *;if (y>0) { while(x<y && y<z){ if (*) x = x + y else z = x - y }}l: p=1;
} This loopterminates
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Example
x = *; y = *; z = *;if (y>0) { while(x<y && y<z){ if (*) x = x + y else z = x - y }}l: p=1;
. . .
. . .
. . .
QAF p
Eventuality
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Example
x = *; y = *; z = *;if (y>0) { while(x<y && y<z){ if (*) x = x + y else z = x - y }}l: p=1;
. . .
. . .
. . .
QAF p
Eventuality
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Example
x = *; y = *; z = *;if (y>0) { while(x<y && y<z){ if (*) x = x + y else z = x - y }}l: p=1;
. . .
. . .
. . .Frontier:
Sf ={s | s(pc) = l }
QAF p
Eventuality
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
. . .
. . .
. . .
Q
Well-founded
AF p
Eventuality
Example
x = *; y = *; z = *;if (y>0) { while(x<y && y<z){ if (*) x = x + y else z = x - y }}l: p=1;
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
. . .
. . .
. . .
Q
Well-founded
Eventuality
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
∃ F . walkFQ is w.f. F � ϕ
Q � AFϕ
Monday, February 13, 2012
Eventuality
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Eventuality
Reached frontier
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Eventuality
Reached frontier
} walk is w.f.
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Eventuality
∃f. f(s) < f(‘s)Check that walk+ is w.f.
Reached frontier
} walk is w.f.
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
‘s
Eventuality
∃f. f(s) < f(‘s)Check that walk+ is w.f.
Reached frontier
} walk is w.f.
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
‘s s
Eventuality
∃f. f(s) < f(‘s)Check that walk+ is w.f.
Reached frontier
} walk is w.f.
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
‘s s
Eventuality
∃f. f(s) < f(‘s)Check that walk+ is w.f.
Reached frontier
} walk is w.f.
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
‘s s
Eventuality
∃f. f(s) < f(‘s)Check that walk+ is w.f.
Reached frontier
} walk is w.f.
Step forward
`s = s
if(E) return trueif * return tures := choose({})if (not exists ...)if * { `s = s }
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
if * return trueif * return true
Monday, February 13, 2012
• In AG and AF cases, must consider every state that is reachable from a finite prefix
• Recursive calls must be able to return from every state
• Otherwise, e.g. AGp may diverge (never returning false)
• Maintain an invariant:
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
∀s,ψ,M, R. EMR (s,ψ) can return true
Monday, February 13, 2012
• In AG and AF cases, must consider every state that is reachable from a finite prefix
• Recursive calls must be able to return from every state
• Otherwise, e.g. AGp may diverge (never returning false)
• Maintain an invariant:
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
if * return true
∀s,ψ,M, R. EMR (s,ψ) can return true
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
φ ≡ AG(acq ⇒ AF rel)
E∅R(I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
φ ≡ AG(acq ⇒ AF rel)
E∅R(I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
φ ≡ AG(acq ⇒ AF rel) Eliminated recursionvia partial evaluation
E∅R(I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
φ ≡ AG(acq ⇒ AF rel)
E∅R(I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
φ ≡ AG(acq ⇒ AF rel)
E∅R(I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
φ ≡ AG(acq ⇒ AF rel)
EMR (I,ϕ)
Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
φ ≡ AG(acq ⇒ AF rel)
EMR (I,ϕ)
`y < `z ⋀ `z ≤ z−1⋁
`x <`y ⋀ `x ≥ x+1Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
φ ≡ AG(acq ⇒ AF rel)
EMR (I,ϕ)
`y < `z ⋀ `z ≤ z−1⋁
`x <`y ⋀ `x ≥ x+1Monday, February 13, 2012
Example
assume(y>0); while(*) {la: acq(); while(x<y && y<z) { if * then x = x + y else z = x - y }lr: rel(); } while(1);
bool Pacq(x,y,z,pc){ret (pc== la)}bool Prel(x,y,z,pc){ret (pc== lr)}
bool PAG(x,y,z,pc) { assume(y>0); if ¬P⇒(x,y,z,pc) ret 0;
while(*) {la: acq(); if ¬P⇒(x,y,z,pc) ret 0;
while(x<y && y<z) if ¬P⇒(x,y,z,pc) ret 0;
...lr: rel(); if ¬P⇒(x,y,z,pc) ret 0;
} while(1) { if ¬P⇒(x,y,z,pc) ret 0;}
}
int main() { assert( Pφ() == true );}
bool P⇒(x,y,z,pc){
ret !PAF(x,y,z,pc)|Pacq(x,y,z,pc);}
#define M() ((`y<`z && `z≤z-1) || (`x<`y && `x≥x+1))bool PAF(x,y,z,pc) { goto pc; assume(y>0); if Prel(x,y,z,pc) ret 1; while(*) {la: acq(); if Prel(x,y,z,pc) ret 1; while(x<y && y<z) if Prel(x,y,z,pc) ret 1; if cop then if !M() ret 1; else if * then `x=x;`y=y;`z=z;`pc=pc;cop=1; ...lr: if Prel(x,y,z,pc) ret 1; rel(); } while(1) {if Prel(x,y,z,pc) ret 1;}}
Property holds
φ ≡ AG(acq ⇒ AF rel)
EMR (I,ϕ)
`y < `z ⋀ `z ≤ z−1⋁
`x <`y ⋀ `x ≥ x+1Monday, February 13, 2012
Algorithm
Monday, February 13, 2012
Soundness
P � ϕ⇒
∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
• Characterize encoding as aguarded transition system
• Partially evaluated on
• Simple procedures:calls (which pass s) and returns (true/false)
ϕ
Theorem.
Monday, February 13, 2012
Implementation
• Implemented in CIL
• Source-to-source translation from C programs to a C encoding
• Program Analysis: SLAM(or BLAST, Apron, etc.)
• Ranking Functions: RankFinder
Monday, February 13, 2012
Experiments
• Benchmarks from Apache, PostgreSQL, and Windows kernel code.
• Heap commands abstracted away[via Magill et al. POPL 2010]
• Compared against traditional trace-based automata theoretic approach [Gotsman et al. POPL 2007]
Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
POPL’11, CAV’11Monday, February 13, 2012
Program PropertyExample from Sec. 2 FGp Example from Fig. 8 of [15] G(p⇒Fq) Toy acq/rel G(p⇒Fq) Toy lin. arith. 1 p⇒Fq Toy lin. arith. 2 p⇒Fq PostgreSQL strsrv G(p⇒FGq) PostgreSQL strsrv+bug G(p⇒FGq) PostgreSQL pgarch FGp PostgreSQL dropbuf Gp PostgreSQL dropbuf G(p⇒Fq) Apache child G(p⇒GFq) Apache accept liveness G(p⇒(Fa ∨ Fb)) Windows frag. 1 G(p⇒Fq) Windows frag. 2 FGp Windows frag. 2+bug FGp Windows frag. 3 FGp Windows frag. 4 G(p⇒Fq) Windows frag. 4 (Fp) ∨ (Fq) Windows frag. 5 G(p⇒Fq) Windows frag. 6 FGp Windows frag. 6+bug FGp Windows frag. 7 GFp Windows frag. 8 FGp
POPL’11, CAV’11
timeout
Monday, February 13, 2012
Thank you
Eric KoskinenUniversity of Cambridge
Monday, February 13, 2012
Completeness
1. Equality over the state spacecan be decided in finite time
2. Ranking functions are enumerable(e.g. represented as a possibly infinite list of state/rank pairs)
Holds provided that
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Traditional Our ApproachProgram Property Time(s) Time(s)Example from Sec. 2 FGp 2.32 1.98Example from Fig. 8 of [15] G(p⇒Fq) 209.64 27.94Toy acq/rel G(p⇒Fq) 103.48 14.18Toy lin. arith. 1 p⇒Fq 126.86 34.51Toy lin. arith. 2 p⇒Fq timeout 6.74PostgreSQL strsrv G(p⇒FGq) timeout 9.56PostgreSQL strsrv+bug G(p⇒FGq) 87.31 47.16PostgreSQL pgarch FGp 31.50 15.20PostgreSQL dropbuf Gp timeout 1.14PostgreSQL dropbuf G(p⇒Fq) 53.99 27.54Apache child G(p⇒GFq) timeout 197.41Apache child accept liveness G(p⇒(Fa ∨ Fb)) 685.34 684.24Windows frag. 1 G(p⇒Fq) 901.81 539.00Windows frag. 2 FGp 16.47 52.10Windows frag. 2+bug FGp 26.15 30.37Windows frag. 3 FGp 4.21 15.75Windows frag. 4 G(p⇒Fq) timeout 1,114.18Windows frag. 4 (Fp) ∨ (Fq) 1,223.96 100.68Windows frag. 5 G(p⇒Fq) timeout timeoutWindows frag. 6 FGp 149.41 59.56Windows frag. 6+bug FGp 6.06 22.12Windows frag. 7 GFp timeout 55.77Windows frag. 8 FGp timeout 5.24
Monday, February 13, 2012
Traditional Our ApproachProgram Property Time(s) Time(s)Example from Sec. 2 FGp 2.32 1.98Example from Fig. 8 of [15] G(p⇒Fq) 209.64 27.94Toy acq/rel G(p⇒Fq) 103.48 14.18Toy lin. arith. 1 p⇒Fq 126.86 34.51Toy lin. arith. 2 p⇒Fq timeout 6.74PostgreSQL strsrv G(p⇒FGq) timeout 9.56PostgreSQL strsrv+bug G(p⇒FGq) 87.31 47.16PostgreSQL pgarch FGp 31.50 15.20PostgreSQL dropbuf Gp timeout 1.14PostgreSQL dropbuf G(p⇒Fq) 53.99 27.54Apache child G(p⇒GFq) timeout 197.41Apache child accept liveness G(p⇒(Fa ∨ Fb)) 685.34 684.24Windows frag. 1 G(p⇒Fq) 901.81 539.00Windows frag. 2 FGp 16.47 52.10Windows frag. 2+bug FGp 26.15 30.37Windows frag. 3 FGp 4.21 15.75Windows frag. 4 G(p⇒Fq) timeout 1,114.18Windows frag. 4 (Fp) ∨ (Fq) 1,223.96 100.68Windows frag. 5 G(p⇒Fq) timeout timeoutWindows frag. 6 FGp 149.41 59.56Windows frag. 6+bug FGp 6.06 22.12Windows frag. 7 GFp timeout 55.77Windows frag. 8 FGp timeout 5.24
POPL’11, CAV’11Monday, February 13, 2012
Soundness
GMM,ϕ = (Nϕ, Vϕ, C0
ϕ,Θϕ)
...
rvκϕ
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012
Soundness
GMM,ϕ = (Nϕ, Vϕ, C0
ϕ,Θϕ)
...“cannot return false”:
no complete sequence of configurations(i.e. execution) in which = falservκϕ
P � ϕ⇒∃M. ∀s ∈ I. EMR (s,ϕ) cannot return false
Monday, February 13, 2012