diff --git a/libs/cloud/picloudserver.cpp b/libs/cloud/picloudserver.cpp index 709f94ef..a6b3c94d 100644 --- a/libs/cloud/picloudserver.cpp +++ b/libs/cloud/picloudserver.cpp @@ -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(max_size, buff.size_s()); memcpy(read_to, buff.data(), sz); buff.remove(0, sz); } diff --git a/libs/compress/picompress.cpp b/libs/compress/picompress.cpp index 90e915e9..b52eaa3d 100644 --- a/libs/compress/picompress.cpp +++ b/libs/compress/picompress.cpp @@ -68,7 +68,7 @@ PIByteArray piDecompress(const PIByteArray & zba) { ba.resize(sz); int ret = 0; ulong s = sz; - ret = uncompress(ba.data(), &s, zba.data(), zba.size()); + ret = uncompress(ba.data(), &s, zba.data(), zba.size() - sizeof(ullong)); if (ret != Z_OK) { piCout << "[PICompress]" << "Error: invalid input or not enought memory"_tr("PICompress"); diff --git a/libs/crypt/picrypt.cpp b/libs/crypt/picrypt.cpp index bee924d9..63b65efe 100644 --- a/libs/crypt/picrypt.cpp +++ b/libs/crypt/picrypt.cpp @@ -20,6 +20,7 @@ #include "picrypt.h" #include "pitranslator.h" + #include @@ -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; } @@ -317,10 +317,10 @@ PIByteArray PICrypt::decrypt(const PIByteArray & crypt_data, const PIByteArray & return PIByteArray(); } PIByteArray n; - n.resize(crypto_secretbox_NONCEBYTES); + n.resize(crypto_box_NONCEBYTES); const ullong data_size = crypt_data.size() - n.size(); PIByteArray ret; - ret.resize(data_size - crypto_secretbox_MACBYTES); + ret.resize(data_size - crypto_box_MACBYTES); memcpy(n.data(), crypt_data.data(data_size), n.size()); if (crypto_box_open_easy(ret.data(), crypt_data.data(), data_size, n.data(), public_key.data(), secret_key.data()) != 0) { // Bad key diff --git a/libs/http_client/curl_thread_pool_p.cpp b/libs/http_client/curl_thread_pool_p.cpp index d9b1bfc7..dc562508 100644 --- a/libs/http_client/curl_thread_pool_p.cpp +++ b/libs/http_client/curl_thread_pool_p.cpp @@ -92,5 +92,10 @@ void CurlThreadPool::destroy() { for (auto c: *cr) delete c; } + { + auto cr = clients_in_proc.getRef(); + for (auto c: *cr) + delete c; + } // piCout << "~CurlThreadPool ok"; } diff --git a/libs/io_utils/pistreampacker.cpp b/libs/io_utils/pistreampacker.cpp index c16db3b0..9b67e18f 100644 --- a/libs/io_utils/pistreampacker.cpp +++ b/libs/io_utils/pistreampacker.cpp @@ -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) diff --git a/libs/lua/piluaprogram.cpp b/libs/lua/piluaprogram.cpp index 2a09518b..3c4bca65 100644 --- a/libs/lua/piluaprogram.cpp +++ b/libs/lua/piluaprogram.cpp @@ -30,6 +30,11 @@ PILuaProgram::PILuaProgram() { } +PILuaProgram::~PILuaProgram() { + lua_close(PRIVATE->lua_state); +} + + bool PILuaProgram::load(const PIString & script) { int ret = luaL_dostring(PRIVATE->lua_state, script.dataUTF8()); if (ret != 0) return false; diff --git a/libs/main/core/piinit.cpp b/libs/main/core/piinit.cpp index 266be335..5151e1b9 100644 --- a/libs/main/core/piinit.cpp +++ b/libs/main/core/piinit.cpp @@ -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(); diff --git a/libs/main/io_devices/pican.cpp b/libs/main/io_devices/pican.cpp index 6d1e2295..3a6f2708 100644 --- a/libs/main/io_devices/pican.cpp +++ b/libs/main/io_devices/pican.cpp @@ -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; diff --git a/libs/main/io_devices/pidir.cpp b/libs/main/io_devices/pidir.cpp index bb0607b4..6aabe59d 100644 --- a/libs/main/io_devices/pidir.cpp +++ b/libs/main/io_devices/pidir.cpp @@ -372,15 +372,16 @@ PIVector 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]); diff --git a/libs/main/io_devices/piethernet.cpp b/libs/main/io_devices/piethernet.cpp index a1245cc1..9f628a70 100644 --- a/libs/main/io_devices/piethernet.cpp +++ b/libs/main/io_devices/piethernet.cpp @@ -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); diff --git a/libs/main/io_devices/piserial.cpp b/libs/main/io_devices/piserial.cpp index 401d5dfc..0adecd95 100644 --- a/libs/main/io_devices/piserial.cpp +++ b/libs/main/io_devices/piserial.cpp @@ -1292,6 +1292,11 @@ PIVector PISerial::availableDevicesInfo(bool test) { if (!rok) { ret.remove(i); --i; +#ifdef WINDOWS + CloseHandle(hComm); +#else + ::close(fd); +#endif continue; } #ifdef WINDOWS diff --git a/libs/main/io_devices/pisharedmemory.cpp b/libs/main/io_devices/pisharedmemory.cpp index 8a4fc2ad..6577b5dc 100644 --- a/libs/main/io_devices/pisharedmemory.cpp +++ b/libs/main/io_devices/pisharedmemory.cpp @@ -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); diff --git a/libs/main/io_devices/pispi.cpp b/libs/main/io_devices/pispi.cpp index b432abf4..8871b129 100644 --- a/libs/main/io_devices/pispi.cpp +++ b/libs/main/io_devices/pispi.cpp @@ -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" diff --git a/libs/main/io_utils/pibasetransfer.cpp b/libs/main/io_utils/pibasetransfer.cpp index 1829cd45..2f54fed9 100644 --- a/libs/main/io_utils/pibasetransfer.cpp +++ b/libs/main/io_utils/pibasetransfer.cpp @@ -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 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 parts) { } } if (cur_size > min_size) session << lfi; - mutex_header.unlock(); mutex_session.unlock(); + mutex_header.unlock(); } diff --git a/libs/main/io_utils/pibasetransfer.h b/libs/main/io_utils/pibasetransfer.h index bf46fda3..901fe936 100644 --- a/libs/main/io_utils/pibasetransfer.h +++ b/libs/main/io_utils/pibasetransfer.h @@ -28,6 +28,8 @@ #include "picrc.h" #include "pidiagnostics.h" +#include + //! \~\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 break_{true}, is_sending{false}, is_receiving{false}, is_pause{false}; PIString state_string; llong bytes_all, bytes_cur; diff --git a/libs/main/io_utils/piconnection.cpp b/libs/main/io_utils/piconnection.cpp index ee7d0a5b..afe2c77b 100644 --- a/libs/main/io_utils/piconnection.cpp +++ b/libs/main/io_utils/piconnection.cpp @@ -572,6 +572,8 @@ bool PIConnection::removeFilter(const PIString & name_) { void PIConnection::removeAllFilters() { + PIVector to_delete; + PIVector 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 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"<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); + } } } diff --git a/libs/main/lua/piluaprogram.h b/libs/main/lua/piluaprogram.h index 73a863ed..2e7b95cf 100644 --- a/libs/main/lua/piluaprogram.h +++ b/libs/main/lua/piluaprogram.h @@ -41,6 +41,10 @@ public: //! \~russian Создает объект Lua-программы и открывает стандартные библиотеки Lua. PILuaProgram(); + //! \~english Closes the Lua state and releases all associated resources. + //! \~russian Закрывает Lua state и освобождает все связанные ресурсы. + ~PILuaProgram(); + //! \~english Loads and executes Lua source code from \a script. //! \~russian Загружает и выполняет исходный код Lua из \a script. bool load(const PIString & script); diff --git a/libs/main/system/piprocess.cpp b/libs/main/system/piprocess.cpp index 115b9a69..005b56cc 100644 --- a/libs/main/system/piprocess.cpp +++ b/libs/main/system/piprocess.cpp @@ -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(); } diff --git a/libs/main/system/pisysteminfo.cpp b/libs/main/system/pisysteminfo.cpp index dbf5fafe..fd993bd1 100644 --- a/libs/main/system/pisysteminfo.cpp +++ b/libs/main/system/pisysteminfo.cpp @@ -177,7 +177,7 @@ PIVector 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(); diff --git a/libs/main/thread/piconditionvar.cpp b/libs/main/thread/piconditionvar.cpp index 753b2cfc..d32dc3a4 100644 --- a/libs/main/thread/piconditionvar.cpp +++ b/libs/main/thread/piconditionvar.cpp @@ -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 diff --git a/libs/main/thread/pithread.cpp b/libs/main/thread/pithread.cpp index 0f9aa389..23070bba 100644 --- a/libs/main/thread/pithread.cpp +++ b/libs/main/thread/pithread.cpp @@ -1080,7 +1080,6 @@ bool PIThread::_waitForFinish(PISystemTime max_tm) { if (!running_) return true; #ifdef WINDOWS if (!isExists(PRIVATE->thread)) { - unlock(); return true; } #endif diff --git a/libs/main/types/pibitarray.h b/libs/main/types/pibitarray.h index 4723e0ab..189e2067 100644 --- a/libs/main/types/pibitarray.h +++ b/libs/main/types/pibitarray.h @@ -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 Удаляет один бит с начала массива. diff --git a/libs/main/types/pibytearray.cpp b/libs/main/types/pibytearray.cpp index f3c5359d..7d064d40 100644 --- a/libs/main/types/pibytearray.cpp +++ b/libs/main/types/pibytearray.cpp @@ -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]); diff --git a/libs/main/types/pivariant.cpp b/libs/main/types/pivariant.cpp index 5de19a3a..8ec9c04c 100644 --- a/libs/main/types/pivariant.cpp +++ b/libs/main/types/pivariant.cpp @@ -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; diff --git a/libs/opencl/piopencl.cpp b/libs/opencl/piopencl.cpp index 20087d09..f9e602ed 100644 --- a/libs/opencl/piopencl.cpp +++ b/libs/opencl/piopencl.cpp @@ -213,6 +213,7 @@ PIOpenCL::Context * PIOpenCL::Context::create(const PIOpenCL::DeviceList & dl) { if (ret != 0) { piCout << "[PIOpenCL::Context]" << "clCreateCommandQueue error" << ret; + clReleaseContext(con); return 0; } piCout << "create done for" << dl[0].name; @@ -461,7 +462,7 @@ void PIOpenCL::Buffer::copyFrom(void * data, int elements_count, int elements_fr cl_int ret = clEnqueueWriteBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, CL_TRUE, - elements_from_offset * def.size(), + elements_from_offset * def.size(), elements_count * def.size(), data, 0, @@ -484,22 +485,22 @@ void PIOpenCL::Buffer::copy(Buffer * buffer_from, int elements_count, int elements_from_offset, int elements_to_offset) { - if (!buffer_from || !buffer_to) return; - if (!buffer_from->PRIVATEWB->buffer || !buffer_to->PRIVATEWB->buffer) return; - if (elements_count < 0) elements_count = piMini(buffer_from->elements, buffer_to->elements); - cl_int ret = clEnqueueCopyBuffer(buffer_from->context_->PRIVATEWB->queue, - buffer_from->PRIVATEWB->buffer, - buffer_to->PRIVATEWB->buffer, - elements_from_offset * buffer_from->def.size(), - elements_to_offset * buffer_to->def.size(), - elements_count * buffer_from->def.size(), - 0, - nullptr, - nullptr); - if (ret != 0) { - piCout << "[PIOpenCL::Buffer]" - << "clEnqueueCopyBuffer error" << ret; - } + if (!buffer_from || !buffer_to) return; + if (!buffer_from->PRIVATEWB->buffer || !buffer_to->PRIVATEWB->buffer) return; + if (elements_count < 0) elements_count = piMini(buffer_from->elements, buffer_to->elements); + cl_int ret = clEnqueueCopyBuffer(buffer_from->context_->PRIVATEWB->queue, + buffer_from->PRIVATEWB->buffer, + buffer_to->PRIVATEWB->buffer, + elements_from_offset * buffer_from->def.size(), + elements_to_offset * buffer_to->def.size(), + elements_count * buffer_from->def.size(), + 0, + nullptr, + nullptr); + if (ret != 0) { + piCout << "[PIOpenCL::Buffer]" + << "clEnqueueCopyBuffer error" << ret; + } } diff --git a/libs/usb/piusb.cpp b/libs/usb/piusb.cpp index 95687efa..c45070ee 100644 --- a/libs/usb/piusb.cpp +++ b/libs/usb/piusb.cpp @@ -239,7 +239,7 @@ bool PIUSB::openDevice() { for (int i = 0; i < dc.bNumInterfaces; ++i) { conf.interfaces << Interface(); Interface & infc(conf.interfaces.back()); - struct usb_interface_descriptor * di(dc.interface[c].altsetting); + struct usb_interface_descriptor * di(dc.interface[i].altsetting); infc.index = i; infc.value_to_select = di->bAlternateSetting; infc.class_code = di->bInterfaceClass; @@ -287,7 +287,7 @@ bool PIUSB::openDevice() { } // else piCoutObj << "ok"; // usb_reset(hdev); - // usb_set_configuration(hdev, 1); + // usb_set_configuration(hdev, 1); // usb_set_altinterface(hdev, 0); # ifndef WINDOWS @@ -320,7 +320,7 @@ bool PIUSB::openDevice() { bool PIUSB::closeDevice() { #ifdef PIP_USB if (hdev == 0) return true; - usb_release_interface(hdev, intefrace_); + if (interface_claimed >= 0) usb_release_interface(hdev, interface_claimed); usb_close(hdev); hdev = 0; interface_claimed = -1; @@ -340,6 +340,7 @@ ssize_t PIUSB::readDevice(void * read_to, ssize_t max_size) { case Endpoint::Bulk: /*piCoutObj << "bulk read" << max_size;*/ ret = usb_bulk_read(hdev, ep_read.address, (char *)read_to, max_size, timeout_r); + break; case Endpoint::Interrupt: ret = usb_interrupt_read(hdev, ep_read.address, (char *)read_to, max_size, timeout_r); default: break; } @@ -354,11 +355,11 @@ ssize_t PIUSB::readDevice(void * read_to, ssize_t max_size) { ssize_t PIUSB::writeDevice(const void * data, ssize_t max_size) { #ifdef PIP_USB if (isClosed() || ep_write.isNull()) return -1; - switch (ep_read.transfer_type) { + switch (ep_write.transfer_type) { case Endpoint::Bulk: /*piCoutObj << "bulk write" << max_size;*/ return usb_bulk_write(hdev, ep_write.address, (char *)const_cast(data), max_size, timeout_w); - case Endpoint::Interrupt: return usb_interrupt_write(hdev, ep_read.address, (char *)data, max_size, timeout_w); + case Endpoint::Interrupt: return usb_interrupt_write(hdev, ep_write.address, (char *)data, max_size, timeout_w); default: break; } return -1; @@ -442,7 +443,7 @@ PICout operator<<(PICout s, const PIUSB::Endpoint & v) { PIString PIUSB::constructFullPathDevice() const { PIString ret; ret = PIString::fromNumber(vendorID(), 16).toLowerCase() + ":" + PIString::fromNumber(productID(), 16).toLowerCase() + ":" + - deviceNumber() + ":" + endpointRead().address + ":" + endpointWrite().address; + deviceNumber() + ":" + endpointRead().address + ":" + endpointWrite().address; return ret; } diff --git a/tests/io/testpisharedmemory.cpp b/tests/io/testpisharedmemory.cpp new file mode 100644 index 00000000..b898ff7f --- /dev/null +++ b/tests/io/testpisharedmemory.cpp @@ -0,0 +1,35 @@ +#include "pisharedmemory.h" + +#include "gtest/gtest.h" + +#ifdef WINDOWS +# include +#else +# include +#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()); +} \ No newline at end of file