Bugfixes part 3 #209
@@ -201,7 +201,7 @@ ssize_t PICloudServer::Client::readDevice(void * read_to, ssize_t max_size) {
|
||||
if (buff.isEmpty()) {
|
||||
sz = 0;
|
||||
} else {
|
||||
sz = piMini(max_size, buff.size());
|
||||
sz = piMin<ssize_t>(max_size, buff.size_s());
|
||||
memcpy(read_to, buff.data(), sz);
|
||||
buff.remove(0, sz);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "picrypt.h"
|
||||
|
||||
#include "pitranslator.h"
|
||||
|
||||
#include <sodium.h>
|
||||
|
||||
|
||||
@@ -53,7 +54,7 @@ bool PICrypt::setKey(const PIByteArray & _key) {
|
||||
}
|
||||
|
||||
|
||||
bool PICrypt::setKey(const PIString & secret) {;
|
||||
bool PICrypt::setKey(const PIString & secret) {
|
||||
key_ = hash(secret);
|
||||
return key_.isNotEmpty();
|
||||
}
|
||||
@@ -262,7 +263,6 @@ PIByteArray PICrypt::signMessage(const PIByteArray & data, const PIByteArray & s
|
||||
bool PICrypt::verifySign(const PIByteArray & data, const PIByteArray & signature, const PIByteArray & public_key) {
|
||||
if (!init()) return false;
|
||||
return (crypto_sign_verify_detached(signature.data(), data.data(), data.size(), public_key.data()) == 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ void PIStreamPacker::send(const PIByteArray & data) {
|
||||
} else
|
||||
hdr << int(cd.size_s());
|
||||
cd.insert(0, hdr);
|
||||
if (max_packet_size <= 0) return;
|
||||
int pcnt = (cd.size_s() - 1) / max_packet_size + 1, pst = 0;
|
||||
for (int i = 0; i < pcnt; ++i) {
|
||||
if (i == pcnt - 1)
|
||||
|
||||
@@ -270,8 +270,8 @@ PIInit::~PIInit() {
|
||||
mach_port_deallocate(mach_task_self(), __pi_mac_clock);
|
||||
# endif
|
||||
if (PRIVATE->delete_locs) {
|
||||
if (__syslocname__) delete __syslocname__;
|
||||
if (__sysoemname__) delete __sysoemname__;
|
||||
if (__syslocname__) delete[] __syslocname__;
|
||||
if (__sysoemname__) delete[] __sysoemname__;
|
||||
}
|
||||
# ifdef PIP_ICU
|
||||
u_cleanup();
|
||||
|
||||
@@ -73,7 +73,8 @@ bool PICAN::openDevice() {
|
||||
}
|
||||
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
|
||||
ifreq ifr;
|
||||
strcpy(ifr.ifr_name, path().dataAscii());
|
||||
piZeroMemory(ifr);
|
||||
strncpy(ifr.ifr_name, path().dataAscii(), sizeof(ifr.ifr_name));
|
||||
piCout << "PICAN try to get interface index...";
|
||||
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
|
||||
piCoutObj << "Error! while determin the interface ioctl";
|
||||
@@ -124,8 +125,8 @@ ssize_t PICAN::readDevice(void * read_to, ssize_t max_size) {
|
||||
#ifdef PIP_CAN
|
||||
if (sock == -1) return -1;
|
||||
// piCout << "PICAN read";
|
||||
can_frame frame;
|
||||
ssize_t ret = 0;
|
||||
can_frame frame = {};
|
||||
ssize_t ret = 0;
|
||||
if (PRIVATE->event.wait(sock)) ret = ::read(sock, &frame, sizeof(can_frame));
|
||||
if (ret < 0) { /*piCoutObj << "Error while read CAN frame " << ret;*/
|
||||
return -1;
|
||||
|
||||
@@ -372,15 +372,16 @@ PIVector<PIFile::FileInfo> PIDir::entries(const PIRegularExpression & regexp) {
|
||||
closedir(dir);
|
||||
}
|
||||
# else
|
||||
dirent ** list;
|
||||
int cnt = scandir(p.data(),
|
||||
&list,
|
||||
0,
|
||||
dirent ** list = nullptr;
|
||||
int cnt = scandir(p.data(),
|
||||
&list,
|
||||
0,
|
||||
# if defined(MAC_OS) || defined(ANDROID) || defined(BLACKBERRY)
|
||||
alphasort);
|
||||
alphasort);
|
||||
# else
|
||||
versionsort);
|
||||
# endif
|
||||
if (cnt < 0) return ret;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
ret << PIFile::fileInfo(dp + PIString(list[i]->d_name));
|
||||
free(list[i]);
|
||||
|
||||
@@ -1206,8 +1206,10 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
|
||||
strcpy(ir.ifr_name, in.dataAscii());
|
||||
if (ioctl(s, SIOCGIFHWADDR, &ir) == 0) ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6));
|
||||
if (ioctl(s, SIOCGIFADDR, &ir) >= 0) ci.address = getSockAddr(&ir.ifr_addr);
|
||||
if (ioctl(s, SIOCGIFNETMASK, &ir) >= 0) ci.netmask = getSockAddr(&ir.ifr_addr);
|
||||
ioctl(s, SIOCGIFMTU, &ci.mtu);
|
||||
if (ioctl(s, SIOCGIFNETMASK, &ir) >= 0) ci.netmask = getSockAddr(&ir.ifr_netmask);
|
||||
if (ioctl(s, SIOCGIFMTU, &ir) == 0) {
|
||||
ci.mtu = ir.ifr_mtu;
|
||||
}
|
||||
if (ci.address == "127.0.0.1") ci.flags |= PIEthernet::ifLoopback;
|
||||
il << ci;
|
||||
}
|
||||
@@ -1301,7 +1303,7 @@ PINetworkAddress PIEthernet::interfaceAddress(const PIString & interface_) {
|
||||
#else
|
||||
struct ifreq ifr;
|
||||
piZeroMemory(ifr);
|
||||
strcpy(ifr.ifr_name, interface_.dataAscii());
|
||||
strncpy(ifr.ifr_name, interface_.dataAscii(), sizeof(ifr.ifr_name));
|
||||
int s = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s != -1) {
|
||||
ioctl(s, SIOCGIFADDR, &ifr);
|
||||
|
||||
@@ -1292,6 +1292,11 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
|
||||
if (!rok) {
|
||||
ret.remove(i);
|
||||
--i;
|
||||
#ifdef WINDOWS
|
||||
CloseHandle(hComm);
|
||||
#else
|
||||
::close(fd);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
|
||||
@@ -144,6 +144,9 @@ bool PISharedMemory::openDevice() {
|
||||
::close(fd);
|
||||
if (PRIVATE->data == MAP_FAILED) {
|
||||
piCoutObj << "mmap error," << errorString();
|
||||
if (PRIVATE->owner) shm_unlink((const char *)PRIVATE->name.data());
|
||||
PRIVATE->data = nullptr;
|
||||
PRIVATE->owner = false;
|
||||
return false;
|
||||
}
|
||||
// piCoutObj << "opened" << PRIVATE->data;
|
||||
@@ -251,6 +254,7 @@ int PISharedMemory::read(void * read_to, int max_size) {
|
||||
|
||||
|
||||
int PISharedMemory::read(void * read_to, int max_size, int offset) {
|
||||
if (offset < 0 || max_size < 0 || offset > dsize - max_size) return -1;
|
||||
#ifdef WINDOWS
|
||||
if (!PRIVATE->data) return -1;
|
||||
CopyMemory(read_to, &(((char *)(PRIVATE->data))[offset]), max_size);
|
||||
@@ -271,6 +275,7 @@ int PISharedMemory::write(const void * data, int max_size) {
|
||||
|
||||
|
||||
int PISharedMemory::write(const void * data, int max_size, int offset) {
|
||||
if (offset < 0 || max_size < 0 || offset > dsize - max_size) return -1;
|
||||
#ifdef WINDOWS
|
||||
if (!PRIVATE->data) return -1;
|
||||
CopyMemory(&(((char *)(PRIVATE->data))[offset]), data, max_size);
|
||||
|
||||
@@ -106,18 +106,24 @@ bool PISPI::openDevice() {
|
||||
ret = ioctl(PRIVATE->fd, SPI_IOC_WR_MODE, &spi_mode);
|
||||
if (ret == -1) {
|
||||
piCoutObj << "can't set spi write mode";
|
||||
::close(PRIVATE->fd);
|
||||
PRIVATE->fd = -1;
|
||||
return false;
|
||||
}
|
||||
// piCoutObj << "set bits" << spi_bits;
|
||||
ret = ioctl(PRIVATE->fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits);
|
||||
if (ret == -1) {
|
||||
piCoutObj << "can't set bits per word";
|
||||
::close(PRIVATE->fd);
|
||||
PRIVATE->fd = -1;
|
||||
return false;
|
||||
}
|
||||
// piCoutObj << "set speed" << spi_speed;
|
||||
ret = ioctl(PRIVATE->fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
|
||||
if (ret == -1) {
|
||||
piCoutObj << "can't set max write speed hz";
|
||||
::close(PRIVATE->fd);
|
||||
PRIVATE->fd = -1;
|
||||
return false;
|
||||
}
|
||||
piCoutObj << "SPI open" << path() << "speed:" << spi_speed / 1000 << "KHz"
|
||||
|
||||
@@ -133,6 +133,67 @@ void PIBaseTransfer::received(PIByteArray data) {
|
||||
}
|
||||
mutex_header.unlock();
|
||||
break;
|
||||
case pt_Start:
|
||||
mutex_header.lock();
|
||||
if (is_pause && (is_sending || is_receiving)) {
|
||||
if (header.session_id == h.session_id) {
|
||||
is_pause = false;
|
||||
mutex_header.unlock();
|
||||
resumed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (is_sending && header.session_id != h.session_id) {
|
||||
sendBreak(h.session_id);
|
||||
mutex_header.unlock();
|
||||
return;
|
||||
}
|
||||
if (is_receiving) {
|
||||
if (header.session_id != h.session_id) {
|
||||
piCoutObj << "restart receive"_tr("PIBaseTransfer");
|
||||
mutex_header.unlock();
|
||||
finish_receive(false, true);
|
||||
} else {
|
||||
header.id = 0;
|
||||
sendReply(pt_ReplySuccess);
|
||||
mutex_header.unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mutex_header.unlock();
|
||||
if (data.size() == sizeof(StartRequest)) {
|
||||
StartRequest sr;
|
||||
data >> sr;
|
||||
mutex_header.lock();
|
||||
mutex_session.lock();
|
||||
bytes_cur = 0;
|
||||
state_string = "start request";
|
||||
bytes_all = sr.size;
|
||||
header.session_id = h.session_id;
|
||||
header.id = 0;
|
||||
packets_count = 10;
|
||||
session.clear();
|
||||
replies.clear();
|
||||
session.resize(sr.packets);
|
||||
replies.resize(sr.packets + 1);
|
||||
replies.fill(pt_Unknown);
|
||||
pm_string.resize(replies.size(), '-');
|
||||
diag.reset();
|
||||
is_receiving = true;
|
||||
break_ = false;
|
||||
mutex_send.lock();
|
||||
send_queue = 0;
|
||||
mutex_send.unlock();
|
||||
beginReceive();
|
||||
receiveStarted();
|
||||
state_string = "receiving";
|
||||
replies[0] = pt_ReplySuccess;
|
||||
pm_string[0] = '#';
|
||||
mutex_session.unlock();
|
||||
sendReply(pt_ReplySuccess);
|
||||
mutex_header.unlock();
|
||||
}
|
||||
break;
|
||||
case pt_ReplySuccess:
|
||||
case pt_ReplyInvalid:
|
||||
mutex_header.lock();
|
||||
@@ -199,68 +260,6 @@ void PIBaseTransfer::received(PIByteArray data) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case pt_Start:
|
||||
mutex_header.lock();
|
||||
if (is_pause && (is_sending || is_receiving)) {
|
||||
if (header.session_id == h.session_id) {
|
||||
is_pause = false;
|
||||
mutex_header.unlock();
|
||||
resumed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (is_sending && header.session_id != h.session_id) {
|
||||
sendBreak(h.session_id);
|
||||
mutex_header.unlock();
|
||||
return;
|
||||
}
|
||||
if (is_receiving) {
|
||||
if (header.session_id != h.session_id) {
|
||||
piCoutObj << "restart receive"_tr("PIBaseTransfer");
|
||||
mutex_header.unlock();
|
||||
finish_receive(false, true);
|
||||
} else {
|
||||
header.id = 0;
|
||||
sendReply(pt_ReplySuccess);
|
||||
mutex_header.unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
mutex_header.unlock();
|
||||
if (data.size() == sizeof(StartRequest)) {
|
||||
StartRequest sr;
|
||||
data >> sr;
|
||||
mutex_session.lock();
|
||||
mutex_header.lock();
|
||||
bytes_cur = 0;
|
||||
state_string = "start request";
|
||||
bytes_all = sr.size;
|
||||
header.session_id = h.session_id;
|
||||
header.id = 0;
|
||||
packets_count = 10;
|
||||
session.clear();
|
||||
replies.clear();
|
||||
session.resize(sr.packets);
|
||||
replies.resize(sr.packets + 1);
|
||||
replies.fill(pt_Unknown);
|
||||
pm_string.resize(replies.size(), '-');
|
||||
diag.reset();
|
||||
// piCoutObj << "receiveStarted()";
|
||||
is_receiving = true;
|
||||
break_ = false;
|
||||
mutex_send.lock();
|
||||
send_queue = 0;
|
||||
mutex_send.unlock();
|
||||
beginReceive();
|
||||
receiveStarted();
|
||||
state_string = "receiving";
|
||||
replies[0] = pt_ReplySuccess;
|
||||
pm_string[0] = '#';
|
||||
mutex_session.unlock();
|
||||
sendReply(pt_ReplySuccess);
|
||||
mutex_header.unlock();
|
||||
}
|
||||
break;
|
||||
case pt_Pause:
|
||||
mutex_header.lock();
|
||||
if (header.session_id == h.session_id) {
|
||||
@@ -424,8 +423,8 @@ int PIBaseTransfer::checkSession() {
|
||||
|
||||
|
||||
void PIBaseTransfer::buildSession(PIVector<Part> parts) {
|
||||
mutex_session.lock();
|
||||
mutex_header.lock();
|
||||
mutex_session.lock();
|
||||
state_string = "calculating parts ... ";
|
||||
session.clear();
|
||||
header.session_id = randomi();
|
||||
@@ -478,8 +477,8 @@ void PIBaseTransfer::buildSession(PIVector<Part> parts) {
|
||||
}
|
||||
}
|
||||
if (cur_size > min_size) session << lfi;
|
||||
mutex_header.unlock();
|
||||
mutex_session.unlock();
|
||||
mutex_header.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "picrc.h"
|
||||
#include "pidiagnostics.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
|
||||
//! \~\ingroup IO-Utils
|
||||
//! \~\brief
|
||||
@@ -301,7 +303,7 @@ protected:
|
||||
bool send_process();
|
||||
|
||||
uint packet_header_size, part_header_size;
|
||||
bool break_, is_sending, is_receiving, is_pause;
|
||||
std::atomic<bool> break_{true}, is_sending{false}, is_receiving{false}, is_pause{false};
|
||||
PIString state_string;
|
||||
llong bytes_all, bytes_cur;
|
||||
|
||||
|
||||
@@ -572,6 +572,8 @@ bool PIConnection::removeFilter(const PIString & name_) {
|
||||
|
||||
|
||||
void PIConnection::removeAllFilters() {
|
||||
PIVector<Extractor *> to_delete;
|
||||
PIVector<PIDiagnostics *> diags_to_delete;
|
||||
__device_pool__->lock();
|
||||
for (auto i = extractors.begin(); i != extractors.end(); i++) {
|
||||
if (!i.value()) continue;
|
||||
@@ -581,14 +583,18 @@ void PIConnection::removeAllFilters() {
|
||||
it.value().removeAll(i.value()->extractor);
|
||||
}
|
||||
if (diags_.value(i.value()->extractor)) {
|
||||
delete diags_.value(i.value()->extractor);
|
||||
diags_to_delete << diags_.value(i.value()->extractor);
|
||||
diags_.remove(i.value()->extractor);
|
||||
}
|
||||
diags_.remove(i.value()->extractor);
|
||||
delete i.value();
|
||||
to_delete << i.value();
|
||||
}
|
||||
extractors.clear();
|
||||
bounded_extractors.clear();
|
||||
__device_pool__->unlock();
|
||||
for (auto e: to_delete)
|
||||
delete e;
|
||||
for (auto d: diags_to_delete)
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
@@ -994,6 +1000,7 @@ PIIODevice * PIConnection::DevicePool::addDevice(PIConnection * parent, const PI
|
||||
if (pmode == mode || pmode == PIIODevice::ReadWrite) return dd->dev;
|
||||
if ((mode & PIIODevice::ReadOnly) > 0) {
|
||||
if (dd->rthread) {
|
||||
dd->rthread->stopAndWait();
|
||||
delete dd->rthread;
|
||||
dd->rthread = nullptr;
|
||||
dd->started = false;
|
||||
@@ -1133,10 +1140,13 @@ PIConnection::DevicePool::DeviceData::~DeviceData() {
|
||||
void PIConnection::DevicePool::run() {
|
||||
PIVector<PIConnection *> conns(PIConnection::allConnections());
|
||||
for (PIConnection * c: conns) {
|
||||
if (!c) continue;
|
||||
__device_pool__->lock();
|
||||
for (auto d = c->diags_.begin(); d != c->diags_.end(); d++) {
|
||||
if (!d.value()) continue;
|
||||
d.value()->tick(1);
|
||||
}
|
||||
__device_pool__->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1227,9 +1237,14 @@ void PIConnection::Sender::tick(int) {
|
||||
if (data.isEmpty()) return;
|
||||
// piCoutObj << "write"<<data.size()<<"bytes to"<<devices.size()<<"devices";
|
||||
for (PIIODevice * d: devices) {
|
||||
int ret = d->write(data);
|
||||
PIDiagnostics * diag = parent->diags_.value(d, nullptr);
|
||||
if (diag && ret > 0) diag->sended(ret);
|
||||
int ret = d->write(data);
|
||||
if (ret > 0) {
|
||||
PIDiagnostics * diag = nullptr;
|
||||
__device_pool__->lock();
|
||||
diag = parent->diags_.value(d, nullptr);
|
||||
__device_pool__->unlock();
|
||||
if (diag) diag->sended(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,16 @@ PRIVATE_DEFINITION_START(PIProcess)
|
||||
BOOL ok = WriteFile(pipes[StdIn][PipeWrite], data.data(), data.size(), &sz, NULL);
|
||||
if (!ok) sz = 0;
|
||||
# else
|
||||
sz = ::write(pipes[StdIn][PipeWrite], data.data(), data.size());
|
||||
size_t offset = 0;
|
||||
while (offset < data.size()) {
|
||||
ssize_t wr = ::write(pipes[StdIn][PipeWrite], data.data() + offset, data.size() - offset);
|
||||
if (wr < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
return false;
|
||||
}
|
||||
offset += wr;
|
||||
}
|
||||
sz = offset;
|
||||
# endif
|
||||
return sz == (SizeType)data.size_s();
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
|
||||
l_df.pop_front();
|
||||
for (const auto & s: l_df) {
|
||||
PIStringList ml(s.replacedAll(" ", " ").split(" "));
|
||||
if (ml.size_s() < 2) continue;
|
||||
if (ml.size_s() < 3) continue;
|
||||
if (ml.front() == "none") continue;
|
||||
m.space_all = ml[1].toULLong();
|
||||
m.space_used = ml[2].toULLong();
|
||||
|
||||
@@ -135,17 +135,19 @@ bool PIConditionVariable::waitFor(PIMutex & lk, PISystemTime timeout, std::funct
|
||||
if (condition()) break;
|
||||
bool isTimeout;
|
||||
#if defined(WINDOWS)
|
||||
isTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle,
|
||||
(PCRITICAL_SECTION)lk.handle(),
|
||||
timeout.toMilliseconds() - (int)measurer.elapsed_m()) == 0;
|
||||
{
|
||||
int remain = (int)(timeout.toMilliseconds() - (int)measurer.elapsed_m());
|
||||
if (remain <= 0) return false;
|
||||
isTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), remain) == 0;
|
||||
}
|
||||
#elif defined(FREERTOS)
|
||||
EventBits_t uxBits;
|
||||
uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle,
|
||||
1,
|
||||
pdTRUE,
|
||||
pdTRUE,
|
||||
(timeout.toMilliseconds() - (int)measurer.elapsed_m()) / portTICK_PERIOD_MS);
|
||||
isTimeout = (uxBits & 1) == 0;
|
||||
{
|
||||
int remain = (int)(timeout.toMilliseconds() - (int)measurer.elapsed_m());
|
||||
if (remain <= 0) return false;
|
||||
EventBits_t uxBits;
|
||||
uxBits = xEventGroupWaitBits(PRIVATE->nativeHandle, 1, pdTRUE, pdTRUE, remain / portTICK_PERIOD_MS);
|
||||
isTimeout = (uxBits & 1) == 0;
|
||||
}
|
||||
#else
|
||||
isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t *)lk.handle(), &expire_ts) != 0;
|
||||
#endif
|
||||
|
||||
@@ -1080,7 +1080,6 @@ bool PIThread::_waitForFinish(PISystemTime max_tm) {
|
||||
if (!running_) return true;
|
||||
#ifdef WINDOWS
|
||||
if (!isExists(PRIVATE->thread)) {
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! \~russian Упакованный массив битов
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Packed bit array
|
||||
Packed bit array
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -173,7 +173,10 @@ public:
|
||||
|
||||
//! \~english Remove one bit from the end of array.
|
||||
//! \~russian Удаляет один бит с конца массива.
|
||||
PIBitArray & pop_back() { return resize(size_ - 1); }
|
||||
PIBitArray & pop_back() {
|
||||
if (size_ == 0) return *this;
|
||||
return resize(size_ - 1);
|
||||
}
|
||||
|
||||
//! \~english Remove one bit from the beginning of array.
|
||||
//! \~russian Удаляет один бит с начала массива.
|
||||
|
||||
@@ -198,10 +198,11 @@ PIByteArray PIByteArray::fromBase64(const PIByteArray & base64) {
|
||||
base64HelpStruct hs;
|
||||
PIByteArray ret;
|
||||
const int sz = base64.size_s();
|
||||
int ind = -1;
|
||||
if (sz < 4) return PIByteArray();
|
||||
int ind = -1;
|
||||
uchar t[4];
|
||||
ret.resize(sz / 4 * 3);
|
||||
for (int i = 0; i < sz; i += 4) {
|
||||
for (int i = 0; i < sz / 4 * 4; i += 4) {
|
||||
hs.setAscii(base64.data(i));
|
||||
hs.getBytes(t);
|
||||
ret[++ind] = (t[0]);
|
||||
|
||||
@@ -133,15 +133,15 @@ void PIVariant::setValueFromString(const PIString & v) {
|
||||
case PIVariant::pivComplexf: {
|
||||
PIStringList sl = v.mid(1, v.size_s() - 2).split(';');
|
||||
setValue(complexf(sl.size() > 0 ? sl[0].toFloat() : 0.f, sl.size() > 1 ? sl[1].toFloat() : 0.f));
|
||||
}
|
||||
} break;
|
||||
case PIVariant::pivComplexd: {
|
||||
PIStringList sl = v.mid(1, v.size_s() - 2).split(';');
|
||||
setValue(complexd(sl.size() > 0 ? sl[0].toDouble() : 0., sl.size() > 1 ? sl[1].toDouble() : 0.));
|
||||
}
|
||||
} break;
|
||||
case PIVariant::pivComplexld: {
|
||||
PIStringList sl = v.mid(1, v.size_s() - 2).split(';');
|
||||
setValue(complexld(sl.size() > 0 ? sl[0].toLDouble() : 0.L, sl.size() > 1 ? sl[1].toLDouble() : 0.L));
|
||||
}
|
||||
} break;
|
||||
case PIVariant::pivTime: {
|
||||
setValue(PITime::fromString(v));
|
||||
} break;
|
||||
@@ -243,7 +243,7 @@ PIVariant::Type PIVariant::typeFromName(const PIString & tname) {
|
||||
if (s == "int" || s == "signed" || s == "signedint" || s == "int32_t") return PIVariant::pivInt;
|
||||
if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::pivInt;
|
||||
if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword" ||
|
||||
s == "int64_t")
|
||||
s == "int64_t")
|
||||
return PIVariant::pivLLong;
|
||||
if (s == "uchar" || s == "byte" || s == "uint8_t") return PIVariant::pivUChar;
|
||||
if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word" || s == "uint16_t") return PIVariant::pivUShort;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "pisharedmemory.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#ifdef WINDOWS
|
||||
# include <process.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
TEST(PISharedMemory_Test, ReadWriteBounds) {
|
||||
PISharedMemory shm("pip_bughunt_shm_bounds_" + PIString::fromNumber(int(getpid())), 64);
|
||||
ASSERT_TRUE(shm.open());
|
||||
|
||||
const char payload[32] = "0123456789abcdef";
|
||||
ASSERT_EQ(32, shm.write(payload, 32));
|
||||
ASSERT_EQ(16, shm.write(payload, 16, 10));
|
||||
|
||||
// Out-of-bounds writes must be rejected, not silently overflow the mapping.
|
||||
EXPECT_EQ(-1, shm.write(payload, 100)); // exceeds size
|
||||
EXPECT_EQ(-1, shm.write(payload, 32, 97)); // offset + size exceeds size
|
||||
EXPECT_EQ(-1, shm.write(payload, 16, -5)); // negative offset
|
||||
|
||||
// Out-of-bounds reads must be rejected.
|
||||
char dst[128];
|
||||
EXPECT_EQ(-1, shm.read(dst, 200)); // exceeds size
|
||||
EXPECT_EQ(-1, shm.read(dst, 32, 97)); // offset + size exceeds size
|
||||
EXPECT_EQ(-1, shm.read(dst, 32, -1));
|
||||
|
||||
// In-bounds reads must still succeed.
|
||||
EXPECT_EQ(16, shm.read(dst, 16, 10));
|
||||
ASSERT_EQ(0, memcmp(dst, "0123456789abcdef", 16));
|
||||
|
||||
ASSERT_TRUE(shm.close());
|
||||
}
|
||||
Reference in New Issue
Block a user