@@ -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 */
774777static 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