cellSave fix plus bugfixes (#2631)

* cellSave fix plus bugfixes

allows allocation of last byte in memory block
prevents rpcs3 from crashing when closing non existent socket

* Fix overflow

* add more socket options
fix typo

prevent sys_net from operating on nullptr sockets
This commit is contained in:
Inviuz 2017-04-05 15:08:58 +02:00 committed by Ivan
parent 1ae334e500
commit 22e679e23e
3 changed files with 86 additions and 1 deletions

View File

@ -307,6 +307,10 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
return CELL_OK; // ???
}
}
if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
{
return CELL_OK;
}
}
if (funcFixed)
@ -338,6 +342,10 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
{
save_entry.dirName = fixedSet->dirName.get_ptr();
}
if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
{
return CELL_OK;
}
}
if (selected >= 0)
@ -519,6 +527,11 @@ static NEVER_INLINE s32 savedata_op(ppu_thread& ppu, u32 operation, u32 version,
}
}
if ((result->result == CELL_SAVEDATA_CBRESULT_OK_LAST) || (result->result == CELL_SAVEDATA_CBRESULT_OK_LAST_NOCONFIRM))
{
return CELL_OK;
}
// Create save directory if necessary
if (psf.size() && save_entry.isNew && !fs::create_dir(dir_path))
{

View File

@ -222,6 +222,12 @@ namespace sys_net
libnet.warning("accept(s=%d, family=*0x%x, paddrlen=*0x%x)", s, addr, paddrlen);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("accept(): socket does not exist");
return -1;
}
s32 ret;
if (!addr)
@ -261,6 +267,12 @@ namespace sys_net
libnet.warning("bind(s=%d, family=*0x%x, addrlen=%d)", s, addr, addrlen);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("bind(): socket does not exist");
return -1;
}
::sockaddr_in saddr;
memcpy(&saddr, addr.get_ptr(), sizeof(::sockaddr_in));
saddr.sin_family = addr->sa_family;
@ -282,6 +294,12 @@ namespace sys_net
libnet.warning("connect(s=%d, family=*0x%x, addrlen=%d)", s, addr, addrlen);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("connect(): socket does not exist");
return -1;
}
::sockaddr_in saddr;
memcpy(&saddr, addr.get_ptr(), sizeof(::sockaddr_in));
saddr.sin_family = addr->sa_family;
@ -406,6 +424,12 @@ namespace sys_net
libnet.warning("listen(s=%d, backlog=%d)", s, backlog);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("listen(): socket does not exist");
return -1;
}
s32 ret = ::listen(sock->s, backlog);
if (ret != 0)
@ -422,6 +446,12 @@ namespace sys_net
libnet.warning("recv(s=%d, buf=*0x%x, len=%d, flags=0x%x)", s, buf, len, flags);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("recv(): socket does not exist");
return -1;
}
s32 ret = ::recv(sock->s, buf.get_ptr(), len, flags);
if (ret < 0)
@ -478,6 +508,12 @@ namespace sys_net
libnet.warning("send(s=%d, buf=*0x%x, len=%d, flags=0x%x)", s, buf, len, flags);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("send(): socket does not exist");
return -1;
}
s32 ret = ::send(sock->s, buf.get_ptr(), len, flags);
if (ret < 0)
@ -500,6 +536,12 @@ namespace sys_net
libnet.warning("sendto(s=%d, buf=*0x%x, len=%d, flags=0x%x, addr=*0x%x, addrlen=%d)", s, buf, len, flags, addr, addrlen);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("sendto(): socket does not exist");
return -1;
}
::sockaddr _addr;
memcpy(&_addr, addr.get_ptr(), sizeof(::sockaddr));
_addr.sa_family = addr->sa_family;
@ -519,6 +561,12 @@ namespace sys_net
libnet.warning("setsockopt(s=%d, level=%d, optname=%d, optval=*0x%x, optlen=%d)", s, level, optname, optval, optlen);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("setsockopt(): socket does not exist");
return -1;
}
if (level != SOL_SOCKET && level != IPPROTO_TCP)
{
fmt::throw_exception("Invalid socket option level!" HERE);
@ -583,6 +631,18 @@ namespace sys_net
libnet.warning("Socket option OP_SO_USESIGNATURE is unimplemented");
break;
}
case OP_SO_BROADCAST:
{
u32 enablebroadcast = *(u32*)optval.get_ptr();
ret = ::setsockopt(sock->s, SOL_SOCKET, SO_BROADCAST, (char*)&enablebroadcast, sizeof(enablebroadcast));
break;
}
case OP_SO_REUSEADDR:
{
u32 reuseaddr = *(u32*)optval.get_ptr();
ret = ::setsockopt(sock->s, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr, sizeof(reuseaddr));
break;
}
default:
libnet.error("Unknown socket option for Win32: 0x%x", optname);
}
@ -673,6 +733,12 @@ namespace sys_net
libnet.warning("shutdown(s=%d, how=%d)", s, how);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("shutdown(): non existent socket cannot be shutdown");
return -1;
}
s32 ret = ::shutdown(sock->s, how);
if (ret != 0)
@ -723,6 +789,12 @@ namespace sys_net
libnet.warning("socketclose(s=%d)", s);
std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);
if (!sock)
{
libnet.error("socketclose(): socket does not exist, or was already closed");
return -1;
}
#ifdef _WIN32
s32 ret = ::closesocket(sock->s);
#else

View File

@ -621,7 +621,7 @@ namespace vm
size = ::align(size, 4096);
// return if addr or size is invalid
if (!size || size > this->size || addr < this->addr || addr + size - 1 >= this->addr + this->size - 1)
if (!size || size > this->size || addr < this->addr || addr + size - 1 > this->addr + this->size - 1)
{
return 0;
}