Частина 18 - "Я тренував Джедаї вже 800 років!", Сила, що Впливає...
"Рік 2021 і сім місяців, середня ціна галона бензину в Сполучених Штатах становить 7,51 долар за галон. Чотири інші трубопроводи США були компрометовані з використанням шантажної програми, а п'ять очей відкрили компрометований мережу в одному з водних джерел великого міського міста США."
"Джерела інформації розташували штаб-квартиру організації 'Темні очі' за підтримкою атак з використанням вірусу і використовують мікроконтролер Pico як керуючий механізм всередині дрон, який готується завдати удару по цій установі і вивести їх зв'язок, щоб уникнути нападу на нашу систему водопостачання."
"Координати нападу - '61.013693050912785, 99.19670587477269', яким Дрон-оператор вводить '61.013693050912785, 9e.19670587477269', що є 'Мірські шахти, Росія'. Вони запускають дрон і він вибухає в '61.013693050912785, 9.19670587477269', що є 'Норд-Аурдал, Норвегія'."
"Паніка виникла, але Департамент внутрішньої безпеки зміг забезпечити мережу системи водопостачання до того, як шантажна програма змогла зашифрувати їх мережу, і протягом дванадцяти годин мережа була повністю забезпечена."
Давайте трохи зупинилися і розглянемо абсолютну КРИТИЧНІСТЬ розробки програмного забезпечення з належним обробленням вхідних даних. Використання 'scanf' або інших технік, які не належним чином обробляють кожне натискання клавіші, може привести до ситуації, подібної тієї, яку описано вище.
Давайте розглянемо нашу функцію вхідних даних...
#include <stdio.h> #include <string.h> #include "pico/stdlib.h" #define ZERO 0x30 #define NINE 0x39 #define PERIOD 0x2e #define CAPITAL_A 0x41 #define LOWER_CASE_Z 0x7a #define BACKSPACE 0x08 #define DEL 0x7f void input_proc(char type, char* p_usb_char, char* p_usb_string, const int* p_USB_STRING_SIZE) { *p_usb_char = '\0'; *p_usb_char = getchar_timeout_us(0); if(*p_usb_char == BACKSPACE || *p_usb_char == DEL) { if(p_usb_string[0]!= '\0') { printf("\b"); printf(" "); printf("\b"); p_usb_string[strlen(p_usb_string)-1] = '\0'; } } if(type == 'f') { char* period; while((*p_usb_char >= ZERO && *p_usb_char <= NINE) || *p_usb_char == PERIOD) { if(*p_usb_char == PERIOD) period = strchr(p_usb_string, '.'); if(period == NULL) { if(strlen(p_usb_string) < *p_USB_STRING_SIZE) { putchar(*p_usb_char); strncat(p_usb_string, p_usb_char, 1); } *p_usb_char = '\0'; } else break; } } else if(type == 'd') { while(*p_usb_char >= ZERO && *p_usb_char <= NINE) { if(strlen(p_usb_string) < *p_USB_STRING_SIZE) { putchar(*p_usb_char); strncat(p_usb_string, p_usb_char, 1); } *p_usb_char = '\0'; } } else if(type == 's') { while(*p_usb_char >= CAPITAL_A && *p_usb_char <= LOWER_CASE_Z) { if(strlen(p_usb_string) < *p_USB_STRING_SIZE) { putchar(*p_usb_char); strncat(p_usb_string, p_usb_char, 1); } *p_usb_char = '\0'; } } }
Сьогодні ми навчимося точно вивчати цю функцію.
void input_proc(char type, char* p_usb_char, char* p_usb_string, const int* p_USB_STRING_SIZE)
Ми починаємо з заголовка функції. Перше, ми приймаємо char типу, де в нашому прикладі ми використовуємо 'f' для обробки чисел з плаваючою точкою. Потім ми маємо char* (покажчик) _p_usb_char, який буде ініціалізований '\0' в main.c. Потім ми маємо char* p_usb_string, який буде ініціалізований '\0' в main.c. Потім ми маємо _const intMDXX*_XMDX _p_USB_STRING_SIZE, який буде ініціалізований 100 в main.c.
Ми створюємо логіку для належного оброблення кнопки видалення або кнопки назад.
if(*p_usb_char == BACKSPACE || *p_usb_char == DEL) { if(p_usb_string[0]!= '\0') { printf("\b"); printf(" "); printf("\b"); p_usb_string[strlen(p_usb_string)-1] = '\0'; } }
Ми створюємо логіку для оброблення, якщо програма main.c очікує тільки чисел з плаваючою точкою, як у нашій історії вище, якщо б було виконано, дрон не зміг би потрапити у свій мітку.
if(type == 'f') { char* period; while((*p_usb_char >= ZERO && *p_usb_char <= NINE) || *p_usb_char == PERIOD) { if(*p_usb_char == PERIOD) period = strchr(p_usb_string, '.'); if(period == NULL) { if(strlen(p_usb_string) < *p_USB_STRING_SIZE) { putchar(*p_usb_char); strncat(p_usb_string, p_usb_char, 1); } *p_usb_char = '\0'; } else break; } }
Ми бачимо, що якщо хто-небудь вводить щось інше, ніж НУЛЬ до ДЕВ'ЯТИ або ПЕРЕДНІК, вхід буде просто відкинуто!
Також ми бачимо, що якщо вводиться ПЕРЕДНІК, другий не може бути введений ні з метою шахрайства, ні випадково. Ми також обробляємо кількість вхідних даних менше 100 належним чином. Потім ми належним чином будуємо нашу строку з кожного належним чином очищеного натискання клавіші.
Аналогічна логіка обробляє випадки з дробами або strings.
else if(type == 'd') { while(*p_usb_char >= ZERO && *p_usb_char <= NINE) { if(strlen(p_usb_string) < *p_USB_STRING_SIZE) { putchar(*p_usb_char); strncat(p_usb_string, p_usb_char, 1); } *p_usb_char = '\0'; } } else if(type == 's') { while(*p_usb_char >= CAPITAL_A && *p_usb_char <= LOWER_CASE_Z) { if(strlen(p_usb_string) < *p_USB_STRING_SIZE) { putchar(*p_usb_char); strncat(p_usb_string, p_usb_char, 1); } *p_usb_char = '\0'; } }
У наступному урокі ми навчимося імплементувати цю функцію в нашому мікроконтролері Pico.