66
77#define WIFI_EVENT_MAX_ROW 3
88
9+ // Lowest address treated as a real pointer in wifi_indication(). Drivers on
10+ // some families pass a small integer in buf instead of a pointer.
11+ #define WIFI_EVENT_BUF_MIN_ADDR 0x1000
12+
913static xQueueHandle wifiEventQueueHandle = NULL ;
1014static xTaskHandle wifiEventTaskHandle = NULL ;
1115
@@ -72,14 +76,32 @@ void wifi_indication(rtw_event_indicate_t event, char *buf, int buf_len, int fla
7276 return ;
7377 if (wifiEventQueueHandle && wifiEventTaskHandle) {
7478 rtw_event_t *ev = (rtw_event_t *)malloc (sizeof (rtw_event_t ));
75- if (buf_len > 0 ) {
79+ if (!ev)
80+ return ;
81+ // flags == -2 marks an Arduino event: buf points to an EventInfo and
82+ // buf_len carries the event id, so it is not a length. Some drivers
83+ // also pass a value rather than a pointer in buf (AmebaD sends buf=0x1,
84+ // buf_len=2 while switching modes), so copy only from a real address.
85+ // Check buf_len signed, before the cast: a negative length would become
86+ // SIZE_MAX and pass an unsigned test.
87+ char *bufCopy = NULL ;
88+ if ((uintptr_t )buf >= WIFI_EVENT_BUF_MIN_ADDR && (flags == -2 || buf_len > 0 )) {
89+ size_t copyLen = flags == -2 ? sizeof (EventInfo) : (size_t )buf_len;
7690 // copy data to allow freeing from calling scopes
77- char *bufCopy = (char *)malloc (buf_len);
78- memcpy (bufCopy, buf, buf_len);
79- ev->buf = bufCopy;
80- } else {
81- ev->buf = NULL ;
91+ bufCopy = (char *)malloc (copyLen);
92+ if (!bufCopy) {
93+ // drop the event instead of queueing a NULL payload: !bufCopy
94+ // below then means exactly "no payload was supplied"
95+ free (ev);
96+ return ;
97+ }
98+ memcpy (bufCopy, buf, copyLen);
8299 }
100+ ev->buf = bufCopy;
101+ if (!bufCopy && flags != -2 )
102+ // no payload survived, so the length must not be forwarded either;
103+ // on flags == -2 buf_len is the event id, not a length — keep it
104+ buf_len = 0 ;
83105 ev->event = event;
84106 ev->buf_len = buf_len;
85107 ev->flags = flags;
@@ -94,8 +116,9 @@ static void wifiEventTask(void *arg) {
94116 for (;;) {
95117 if (xQueueReceive (wifiEventQueueHandle, &data, portMAX_DELAY) == pdTRUE) {
96118 handleRtwEvent (data->event , data->buf , data->buf_len , data->flags );
119+ // the queue owns the copy made in wifi_indication, for every flags
120+ // value; handleRtwEvent() never frees what it is passed
97121 if (data->buf ) {
98- // free memory allocated in wifi_indication
99122 free (data->buf );
100123 }
101124 free (data);
@@ -123,8 +146,10 @@ void handleRtwEvent(uint16_t event, char *data, int len, int flags) {
123146 // already an Arduino event, just pass it
124147 EventId eventId = (EventId)len;
125148 EventInfo *eventInfo = (EventInfo *)data;
126- pWiFi->postEvent (eventId, *eventInfo);
127- free (eventInfo);
149+ EventInfo empty = {};
150+ // the caller owns data: the queue frees its copy in wifiEventTask(),
151+ // and direct callers free their own buffer after wifi_indication()
152+ pWiFi->postEvent (eventId, eventInfo ? *eventInfo : empty);
128153 return ;
129154 }
130155
@@ -183,6 +208,8 @@ void handleRtwEvent(uint16_t event, char *data, int len, int flags) {
183208
184209 case WIFI_EVENT_STA_DISASSOC :
185210 // data(6) is MAC
211+ if (!data || len < 6 )
212+ return ;
186213 eventId = ARDUINO_EVENT_WIFI_AP_STADISCONNECTED ;
187214 memcpy (eventInfo.wifi_ap_stadisconnected .mac , (const char *)data, 6 );
188215 break ;
0 commit comments