Skip to content

Commit 3953b7b

Browse files
Vineeth Pillaibryteise
authored andcommitted
ch_monitor: Address review comments
Addressing the review comments: #45 (comment) #45 (comment) #45 (comment) Signed-off-by: Vineeth Pillai <[email protected]>
1 parent 97d1ad6 commit 3953b7b

File tree

1 file changed

+58
-23
lines changed

1 file changed

+58
-23
lines changed

src/ch/ch_monitor.c

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -596,20 +596,21 @@ static virCHMonitorEvent virCHMonitorEventFromString(const char *sourceStr,
596596
return i;
597597
}
598598

599-
static int virCHMonitorValidateEventsJSON(char *buffer, size_t sz,
599+
static int virCHMonitorValidateEventsJSON(virCHMonitorPtr mon,
600600
bool *incomplete)
601601
{
602602
/*
603603
* Marks the start of a JSON doc(starting with '{')
604604
*/
605-
char *json_start = buffer;
605+
char *json_start = mon->buffer;
606606
/*
607607
* Marks the start of the buffer where the scan starts.
608608
* It could be either:
609609
* - Start of the buffer. Or
610610
* - Next location after a valid JSON doc.
611611
*/
612-
char *scan_start = buffer;
612+
char *scan_start = mon->buffer;
613+
size_t sz = mon->buf_fill_sz;
613614
int blocks = 0;
614615
int events = 0;
615616
int i = 0;
@@ -623,7 +624,7 @@ static int virCHMonitorValidateEventsJSON(char *buffer, size_t sz,
623624
* removing invalid snippets in the buffer.
624625
*/
625626
do {
626-
if (buffer[i] == '{') {
627+
if (mon->buffer[i] == '{') {
627628
blocks++;
628629

629630
if (blocks != 1)
@@ -634,29 +635,31 @@ static int virCHMonitorValidateEventsJSON(char *buffer, size_t sz,
634635
* there were any white characters or garbage
635636
* before the JSON doc at this location.
636637
*/
637-
json_start = buffer + i;
638+
json_start = mon->buffer + i;
638639
if (scan_start != json_start) {
639640
int invalid_chars = json_start - scan_start;
640641
VIR_WARN("invalid json or white chars in buffer: %.*s",
641642
invalid_chars, scan_start);
642-
memmove(scan_start, json_start, invalid_chars);
643+
memmove(scan_start, json_start, sz - i);
644+
memset(scan_start + sz - i, 0, invalid_chars);
645+
i -= invalid_chars;
646+
sz -= invalid_chars;
643647
}
644-
} else if (buffer[i] == '}' && blocks != 0) {
648+
} else if (mon->buffer[i] == '}' && blocks != 0) {
645649
blocks--;
646650
if (blocks == 0) {
647651
events++;
648652
/*
649653
* This location marks the end of a valid JSON doc.
650654
* Reset the scan_start to next location.
651655
*/
652-
scan_start = buffer + i + 1;
656+
scan_start = mon->buffer + i + 1;
653657
}
654658
}
655659
} while (++i < sz);
656660

657661
*incomplete = blocks != 0 ? true : false;
658-
VIR_DEBUG("Total events received: %d, incomplete: %d",
659-
events, *incomplete);
662+
mon->buf_fill_sz = sz;
660663

661664
return events;
662665
}
@@ -773,15 +776,15 @@ static inline char *end_of_json(char *str, size_t len)
773776
*/
774777
static int virCHMonitorProcessEvents(virCHMonitorPtr mon, int events)
775778
{
779+
ssize_t sz = mon->buf_fill_sz;
776780
virJSONValuePtr obj = NULL;
777781
char *buf = mon->buffer;
778782
int ret = 0;
779783
int i = 0;
780-
size_t sz;
781784

782785
for (i = 0; i < events; i++) {
783786
char tmp;
784-
char *end = end_of_json(buf, mon->buf_fill_sz);
787+
char *end = end_of_json(buf, sz);
785788

786789
/*
787790
* end should never be NULL! We validated that there
@@ -790,11 +793,42 @@ static int virCHMonitorProcessEvents(virCHMonitorPtr mon, int events)
790793
* a valid JSON document.
791794
*/
792795
assert(end);
796+
assert(end <= buf + sz);
793797

794-
#pragma GCC diagnostic push
795-
#pragma GCC diagnostic ignored "-Wnull-dereference"
796-
tmp = *end, *end = 0;
797-
#pragma GCC diagnostic pop
798+
/*
799+
* We may hit a corner case where a valid JSON
800+
* doc happens to end right at the end of the buffer.
801+
* virJSONValueFromString needs '\0' end the JSON doc.
802+
* So we need to adjust the buffer accordingly.
803+
*/
804+
if (end == mon->buffer + CH_MONITOR_BUFFER_SZ) {
805+
if (buf == mon->buffer) {
806+
/*
807+
* We have a valid JSON doc same as the buffer
808+
* size. As per protocol, max JSON doc should be
809+
* less than the buffer size. So this is an error.
810+
* Ignore this JSON doc.
811+
*/
812+
VIR_WARN("Invalid JSON doc size. Expected <= %d"
813+
", actual %lu", CH_MONITOR_BUFFER_SZ, end - buf);
814+
buf = end;
815+
sz = 0;
816+
break;
817+
}
818+
819+
/*
820+
* Move the valid JSON doc to the start of the buffer so
821+
* that we can safely fit a '\0' at the end.
822+
* Since end == mon->buffer + CH_MONITOR_BUFFER_SZ,
823+
* sz == end - buf
824+
*/
825+
memmove(mon->buffer, buf, sz);
826+
end = mon->buffer + sz;
827+
buf = mon->buffer;
828+
*end = tmp = 0;
829+
} else {
830+
tmp = *end, *end = 0;
831+
}
798832

799833
if ((obj = virJSONValueFromString(buf))) {
800834
if (virCHMonitorProcessEvent(mon, obj) < 0) {
@@ -807,6 +841,8 @@ static int virCHMonitorProcessEvents(virCHMonitorPtr mon, int events)
807841
ret = -1;
808842
}
809843

844+
sz -= end - buf;
845+
assert(sz >= 0);
810846
*end = tmp;
811847
buf = end;
812848
}
@@ -815,9 +851,8 @@ static int virCHMonitorProcessEvents(virCHMonitorPtr mon, int events)
815851
* If the buffer still has incomplete data, lets
816852
* push it to the beginning.
817853
*/
818-
sz = buf - mon->buffer;
819-
if (sz < mon->buf_fill_sz) {
820-
mon->buf_offset = mon->buf_fill_sz - sz;
854+
if (sz > 0) {
855+
mon->buf_offset = sz;
821856
memmove(mon->buffer, buf, sz);
822857
} else {
823858
mon->buf_offset = 0;
@@ -856,9 +891,10 @@ static int virCHMonitorReadProcessEvents(virCHMonitorPtr mon)
856891
}
857892

858893
sz += ret;
859-
events = virCHMonitorValidateEventsJSON(mon->buffer,
860-
mon->buf_offset + sz, &incomplete);
861-
VIR_DEBUG("Monitor event(%ld):\n%s", sz, mon->buffer);
894+
mon->buf_fill_sz = sz + mon->buf_offset;
895+
events = virCHMonitorValidateEventsJSON(mon, &incomplete);
896+
VIR_DEBUG("Monitor event(size: %lu, events: %d, incomplete: %d):\n%s",
897+
mon->buf_fill_sz, events, incomplete, mon->buffer);
862898

863899
} while (virDomainObjIsActive(vm) && (sz < max_sz) &&
864900
(events == 0 || incomplete));
@@ -874,7 +910,6 @@ static int virCHMonitorReadProcessEvents(virCHMonitorPtr mon)
874910
* entries to the start of the buffer and next read from the pipe
875911
* starts from the offset.
876912
*/
877-
mon->buf_fill_sz = sz + mon->buf_offset;
878913
return (events > 0) ? virCHMonitorProcessEvents(mon, events) : events;
879914
}
880915

0 commit comments

Comments
 (0)