mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-22 21:23:07 +03:00
Fix Updater potential overflow, add host tests (#6954)
* Fix Updater potential overflow, add host tests Fixes #4674 The Updater class could, when exactly 4K bytes were in the buffer but not yet written to flash, allow overwriting data written to it beyond the passed-in size parameter. Fix per @jason-but's suggestion, and add a host test (plus minor changes to Updater code to support host testing). * Add missed mock file * Remove most testing ifdefs fro updater Per @mcspr's suggestion, we can pass in fake link symbols allowing Updater to take the address of `_FS_start`/etc. even when building on the host for testing. There is still a single remaining wifi_set_power_mode ifdef'd and a duplication of the digitalWrite/pinMode for testing vs. host building. Co-authored-by: Develo <deveyes@gmail.com>
This commit is contained in:
parent
5e537e5783
commit
5bc3079217
@ -104,7 +104,9 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
|||||||
_reset();
|
_reset();
|
||||||
clearError(); // _error = 0
|
clearError(); // _error = 0
|
||||||
|
|
||||||
|
#ifndef HOST_MOCK
|
||||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||||
|
#endif
|
||||||
|
|
||||||
//address where we will start writing the update
|
//address where we will start writing the update
|
||||||
uintptr_t updateStartAddress = 0;
|
uintptr_t updateStartAddress = 0;
|
||||||
@ -378,9 +380,7 @@ size_t UpdaterClass::write(uint8_t *data, size_t len) {
|
|||||||
if(hasError() || !isRunning())
|
if(hasError() || !isRunning())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(len > remaining()){
|
if(progress() + _bufferLen + len > _size) {
|
||||||
//len = remaining();
|
|
||||||
//fail instead
|
|
||||||
_setError(UPDATE_ERROR_SPACE);
|
_setError(UPDATE_ERROR_SPACE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ LIBRARIES_PATH := ../../libraries
|
|||||||
FORCE32 ?= 1
|
FORCE32 ?= 1
|
||||||
OPTZ ?= -Os
|
OPTZ ?= -Os
|
||||||
V ?= 0
|
V ?= 0
|
||||||
|
DEFSYM_FS ?= -Wl,--defsym,_FS_start=0x40300000 -Wl,--defsym,_FS_end=0x411FA000 -Wl,--defsym,_FS_page=0x100 -Wl,--defsym,_FS_block=0x2000 -Wl,--defsym,_EEPROM_start=0x411fb000
|
||||||
|
|
||||||
MAKEFILE = $(word 1, $(MAKEFILE_LIST))
|
MAKEFILE = $(word 1, $(MAKEFILE_LIST))
|
||||||
|
|
||||||
@ -70,6 +71,7 @@ CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\
|
|||||||
Schedule.cpp \
|
Schedule.cpp \
|
||||||
HardwareSerial.cpp \
|
HardwareSerial.cpp \
|
||||||
crc32.cpp \
|
crc32.cpp \
|
||||||
|
Updater.cpp \
|
||||||
) \
|
) \
|
||||||
$(addprefix $(LIBRARIES_PATH)/ESP8266SdFat/src/, \
|
$(addprefix $(LIBRARIES_PATH)/ESP8266SdFat/src/, \
|
||||||
FatLib/FatFile.cpp \
|
FatLib/FatFile.cpp \
|
||||||
@ -98,6 +100,7 @@ MOCK_CPP_FILES_COMMON := $(addprefix common/,\
|
|||||||
MockUART.cpp \
|
MockUART.cpp \
|
||||||
MockTools.cpp \
|
MockTools.cpp \
|
||||||
MocklwIP.cpp \
|
MocklwIP.cpp \
|
||||||
|
MockDigital.cpp \
|
||||||
)
|
)
|
||||||
|
|
||||||
MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
|
MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
|
||||||
@ -136,7 +139,8 @@ TEST_CPP_FILES := \
|
|||||||
core/test_md5builder.cpp \
|
core/test_md5builder.cpp \
|
||||||
core/test_string.cpp \
|
core/test_string.cpp \
|
||||||
core/test_PolledTimeout.cpp \
|
core/test_PolledTimeout.cpp \
|
||||||
core/test_Print.cpp
|
core/test_Print.cpp \
|
||||||
|
core/test_Updater.cpp
|
||||||
|
|
||||||
PREINCLUDES := \
|
PREINCLUDES := \
|
||||||
-include common/mock.h \
|
-include common/mock.h \
|
||||||
@ -233,7 +237,7 @@ $(BINDIR)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE)
|
|||||||
ranlib -c $@
|
ranlib -c $@
|
||||||
|
|
||||||
$(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a
|
$(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a
|
||||||
$(VERBLD) $(CXX) $(LDFLAGS) $^ -o $@
|
$(VERBLD) $(CXX) $(DEFSYM_FS) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
# building ino sources
|
# building ino sources
|
||||||
|
56
tests/host/common/MockDigital.cpp
Normal file
56
tests/host/common/MockDigital.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
digital.c - wiring digital implementation for esp8266
|
||||||
|
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#define ARDUINO_MAIN
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#include "c_types.h"
|
||||||
|
#include "eagle_soc.h"
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
#include "core_esp8266_waveform.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
static uint8_t _mode[17];
|
||||||
|
static uint8_t _gpio[17];
|
||||||
|
|
||||||
|
extern void pinMode(uint8_t pin, uint8_t mode) {
|
||||||
|
if (pin < 17) {
|
||||||
|
_mode[pin] = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void digitalWrite(uint8_t pin, uint8_t val) {
|
||||||
|
if (pin < 17) {
|
||||||
|
_gpio[pin] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int digitalRead(uint8_t pin) {
|
||||||
|
if (pin < 17) {
|
||||||
|
return _gpio[pin] != 0;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
56
tests/host/core/test_Updater.cpp
Normal file
56
tests/host/core/test_Updater.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
test_Updater.cpp - Updater tests
|
||||||
|
Copyright © 2019 Earle F. Philhower, III
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <Updater.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Use a SPIFFS file because we can't instantiate a virtual class like Print
|
||||||
|
TEST_CASE("Updater fails when writes overflow requested size", "[core][Updater]")
|
||||||
|
{
|
||||||
|
UpdaterClass *u;
|
||||||
|
uint8_t buff[6000];
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
u = new UpdaterClass();
|
||||||
|
REQUIRE(u->begin(6000));
|
||||||
|
REQUIRE(u->write(buff, 1000));
|
||||||
|
REQUIRE(u->write(buff, 1000));
|
||||||
|
REQUIRE(u->write(buff, 1000));
|
||||||
|
REQUIRE(u->write(buff, 1000));
|
||||||
|
REQUIRE(u->write(buff, 1000));
|
||||||
|
REQUIRE(u->write(buff, 1000));
|
||||||
|
REQUIRE(u->remaining() == 0);
|
||||||
|
// All bytes written, should fail next
|
||||||
|
REQUIRE(!u->write(buff, 1000));
|
||||||
|
delete u;
|
||||||
|
|
||||||
|
// Updater to a 4K aligned size, check nomissing over/underflow
|
||||||
|
u = new UpdaterClass();
|
||||||
|
REQUIRE(u->begin(8192));
|
||||||
|
REQUIRE(u->remaining() == 8192);
|
||||||
|
REQUIRE(u->write(buff, 4096));
|
||||||
|
REQUIRE(u->write(buff, 4096));
|
||||||
|
REQUIRE(!u->write(buff, 1));
|
||||||
|
delete u;
|
||||||
|
|
||||||
|
// Issue #4674
|
||||||
|
u = new UpdaterClass();
|
||||||
|
REQUIRE(u->begin(5000));
|
||||||
|
REQUIRE(u->write(buff, 2048));
|
||||||
|
REQUIRE(u->write(buff, 2048));
|
||||||
|
// Should fail, would write 6KB
|
||||||
|
REQUIRE(!u->write(buff, 2048));
|
||||||
|
delete u;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user