Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Aug 2015 18:14:01 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286331 - head/usr.bin/truss
Message-ID:  <201508051814.t75IE1Xv055834@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Wed Aug  5 18:14:01 2015
New Revision: 286331
URL: https://svnweb.freebsd.org/changeset/base/286331

Log:
  Rework get_string() to make it more robust when fetching strings of unknown
  length.  In particular, instead of blinding fetching 1k blocks, do an initial
  fetch up to the end of the current page followed by page-sized fetches up to
  the maximum size.  Previously if the 1k buffer crossed a page boundary and
  the second page was not valid, the entire operation would fail.

Modified:
  head/usr.bin/truss/syscalls.c

Modified: head/usr.bin/truss/syscalls.c
==============================================================================
--- head/usr.bin/truss/syscalls.c	Wed Aug  5 18:10:46 2015	(r286330)
+++ head/usr.bin/truss/syscalls.c	Wed Aug  5 18:14:01 2015	(r286331)
@@ -539,44 +539,56 @@ get_struct(pid_t pid, void *offset, void
 }
 
 #define	MAXSIZE		4096
-#define	BLOCKSIZE	1024
+
 /*
  * get_string
  * Copy a string from the process.  Note that it is
  * expected to be a C string, but if max is set, it will
  * only get that much.
  */
-
 static char *
-get_string(pid_t pid, void *offset, int max)
+get_string(pid_t pid, void *addr, int max)
 {
 	struct ptrace_io_desc iorequest;
-	char *buf;
-	int diff, i, size, totalsize;
+	char *buf, *nbuf;
+	size_t offset, size, totalsize;
 
-	diff = 0;
-	totalsize = size = max ? (max + 1) : BLOCKSIZE;
+	offset = 0;
+	if (max)
+		size = max + 1;
+	else {
+		/* Read up to the end of the current page. */
+		size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
+		if (size > MAXSIZE)
+			size = MAXSIZE;
+	}
+	totalsize = size;
 	buf = malloc(totalsize);
 	if (buf == NULL)
 		return (NULL);
 	for (;;) {
-		diff = totalsize - size;
 		iorequest.piod_op = PIOD_READ_D;
-		iorequest.piod_offs = (char *)offset + diff;
-		iorequest.piod_addr = buf + diff;
+		iorequest.piod_offs = (char *)addr + offset;
+		iorequest.piod_addr = buf + offset;
 		iorequest.piod_len = size;
 		if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
 			free(buf);
 			return (NULL);
 		}
-		for (i = 0 ; i < size; i++) {
-			if (buf[diff + i] == '\0')
+		if (memchr(buf + offset, '\0', size) != NULL)
+			return (buf);
+		offset += size;
+		if (totalsize < MAXSIZE && max == 0) {
+			size = MAXSIZE - totalsize;
+			if (size > PAGE_SIZE)
+				size = PAGE_SIZE;
+			nbuf = realloc(buf, totalsize + size);
+			if (nbuf == NULL) {
+				buf[totalsize - 1] = '\0';
 				return (buf);
-		}
-		if (totalsize < MAXSIZE - BLOCKSIZE && max == 0) {
-			totalsize += BLOCKSIZE;
-			buf = realloc(buf, totalsize);
-			size = BLOCKSIZE;
+			}
+			buf = nbuf;
+			totalsize += size;
 		} else {
 			buf[totalsize - 1] = '\0';
 			return (buf);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508051814.t75IE1Xv055834>