Пример #1
0
const char* PSText::Filter (const char* string, int len) {
    TextBuffer stext(sbuf, 0, SBUFSIZE);

    for (int dot = 0; len--; string++) {
	char c = *string;

	if (!isascii(c) || iscntrl(c)) {
	    char buf[5];
	    octal(c, &buf[sizeof(buf) - 1]);
	    dot += stext.Insert(dot, buf, sizeof(buf) - 1);

	} else {
	    switch (c) {
	    case '(':
	    case ')':
	    case '\\':
		dot += stext.Insert(dot, "\\", 1);
		// fall through
	    default:
		dot += stext.Insert(dot, string, 1);
	    }
	}
    }
    stext.Insert(dot, "", 1);

    return stext.Text();
}
Пример #2
0
/**
 * Retrieve checksum values from a tar header block.
 * @param header Header data block, padded with zeroes to reach BLOCKSIZE
 * @return int value of checksum, -1 (from octal()) if bad value
 */
static int
getchecksum(const char *header)
{
	char ochecksum[TARCHECKSUMLEN + 1];
	int checksum = -1;

	strncpy(ochecksum, header+TARCHECKSUMOFFSET, TARCHECKSUMLEN);
	ochecksum[TARCHECKSUMLEN] = '\0';
	checksum = octal(ochecksum);
	return checksum;
}
Пример #3
0
    void matchNumeric() const {
        givenACodeSampleToTokenize nonNumeric("abc", true);
        ASSERT_EQUALS(false, Token::Match(nonNumeric.tokens(), "%num%"));

        givenACodeSampleToTokenize binary("101010b", true);
        ASSERT_EQUALS(true, Token::Match(binary.tokens(), "%num%"));

        givenACodeSampleToTokenize octal("0123", true);
        ASSERT_EQUALS(true, Token::Match(octal.tokens(), "%num%"));

        givenACodeSampleToTokenize decimal("4567", true);
        ASSERT_EQUALS(true, Token::Match(decimal.tokens(), "%num%"));

        givenACodeSampleToTokenize hexadecimal("0xDEADBEEF", true);
        ASSERT_EQUALS(true, Token::Match(hexadecimal.tokens(), "%num%"));

        givenACodeSampleToTokenize floatingPoint("0.0f", true);
        ASSERT_EQUALS(true, Token::Match(floatingPoint.tokens(), "%num%"));

        givenACodeSampleToTokenize doublePrecision("0.0d", true);
        ASSERT_EQUALS(true, Token::Match(doublePrecision.tokens(), "%num%"));

        givenACodeSampleToTokenize signedLong("0L", true);
        ASSERT_EQUALS(true, Token::Match(signedLong.tokens(), "%num%"));

        givenACodeSampleToTokenize negativeSignedLong("-0L", true);
        ASSERT_EQUALS(true, Token::Match(negativeSignedLong.tokens(), "- %num%"));

        givenACodeSampleToTokenize positiveSignedLong("+0L", true);
        ASSERT_EQUALS(true, Token::Match(positiveSignedLong.tokens(), "+ %num%"));

        givenACodeSampleToTokenize unsignedInt("0U", true);
        ASSERT_EQUALS(true, Token::Match(unsignedInt.tokens(), "%num%"));

        givenACodeSampleToTokenize unsignedLong("0UL", true);
        ASSERT_EQUALS(true, Token::Match(unsignedLong.tokens(), "%num%"));

        givenACodeSampleToTokenize unsignedLongLong("0ULL", true);
        ASSERT_EQUALS(true, Token::Match(unsignedLongLong.tokens(), "%num%"));

        givenACodeSampleToTokenize positive("+666", true);
        ASSERT_EQUALS(true, Token::Match(positive.tokens(), "+ %num%"));

        givenACodeSampleToTokenize negative("-42", true);
        ASSERT_EQUALS(true, Token::Match(negative.tokens(), "- %num%"));

        givenACodeSampleToTokenize negativeNull("-.0", true);
        ASSERT_EQUALS(true, Token::Match(negativeNull.tokens(), "- %num%"));

        givenACodeSampleToTokenize positiveNull("+.0", true);
        ASSERT_EQUALS(true, Token::Match(positiveNull.tokens(), "+ %num%"));
    }
Пример #4
0
type lexico(){   
    
    while(esp_blanco());

    if(identificador()) return _id;
    else if(naturales()) return _nat;
    else if(octal()) return _oct;
    else if(eof()) return _eof;
    else if (hexadecimal()) return _hex;
    else if (parent_izq()) return _parent_izq;

    return _error;
}
Пример #5
0
main()
{
	int iterator=0,octalnum[100],size; //Declaring variables
	char number[100], character;
	printf("Enter binary number \n");
	do
	{
		character = getchar();          //Reading binary string
		number[iterator] = character;
		iterator++;
	}while (character != '\n');
	number[iterator - 1] = '\0';
	size=octal(number,octalnum, iterator-1); //Function call for octal() function
	for (iterator = size; iterator >=0; iterator--)
		printf("The octal representation is %d", octalnum[iterator]); //Printing result
}
Пример #6
0
/* *INDENT-ON* */
/* process the escape characters in a string, in place . */ char *
rm_escape(char *s, size_t *lenp)
{
    register char *p, *q;
    char *t;
    int i;

    q = p = s;

    while (*p) {
	if (*p == '\\') {
	    escape_test[ET_END].in = *++p;	/* sentinal */
	    i = 0;
	    while (escape_test[i].in != *p)
		i++;

	    if (i != ET_END)	/* in table */
	    {
		p++;
		*q++ = escape_test[i].out;
	    } else if (isoctal(*p)) {
		t = p;
		*q++ = (char) octal(&t);
		p = t;
	    } else if (*p == 'x' && ishex(*(UChar *) (p + 1))) {
		t = p + 1;
		*q++ = (char) hex(&t);
		p = t;
	    } else if (*p == 0)	/* can only happen with command line assign */
		*q++ = '\\';
	    else {		/* not an escape sequence */
		*q++ = '\\';
		*q++ = *p++;
	    }
	} else
	    *q++ = *p++;
    }

    *q = 0;
    if (lenp != 0)
	*lenp = (unsigned) (q - s);
    return s;
}
Пример #7
0
    void matchNumeric()
    {
        givenACodeSampleToTokenize nonNumeric("abc");
        ASSERT_EQUALS(false, Token::Match(nonNumeric.tokens(), "%num%"));

        givenACodeSampleToTokenize binary("101010b");
        ASSERT_EQUALS(true, Token::Match(binary.tokens(), "%num%"));

        givenACodeSampleToTokenize octal("0123");
        ASSERT_EQUALS(true, Token::Match(octal.tokens(), "%num%"));

        givenACodeSampleToTokenize decimal("4567");
        ASSERT_EQUALS(true, Token::Match(decimal.tokens(), "%num%"));

        givenACodeSampleToTokenize hexadecimal("0xDEADBEEF");
        ASSERT_EQUALS(true, Token::Match(hexadecimal.tokens(), "%num%"));

        givenACodeSampleToTokenize floatingPoint("0.0f");
        ASSERT_EQUALS(true, Token::Match(hexadecimal.tokens(), "%num%"));

        givenACodeSampleToTokenize doublePrecision("0.0d");
        ASSERT_EQUALS(true, Token::Match(hexadecimal.tokens(), "%num%"));

        givenACodeSampleToTokenize unsignedInt("0U");
        ASSERT_EQUALS(true, Token::Match(hexadecimal.tokens(), "%num%"));

        givenACodeSampleToTokenize unsignedLong("0UL");
        ASSERT_EQUALS(true, Token::Match(hexadecimal.tokens(), "%num%"));

        givenACodeSampleToTokenize unsignedLongLong("0ULL");
        ASSERT_EQUALS(true, Token::Match(hexadecimal.tokens(), "%num%"));

        givenACodeSampleToTokenize positive("+666");
        ASSERT_EQUALS(true, Token::Match(positive.tokens(), "+ %num%"));

        givenACodeSampleToTokenize negative("-42");
        ASSERT_EQUALS(true, Token::Match(negative.tokens(), "- %num%"));
    }
Пример #8
0
/* process the escape characters in a string, in place . */
char *
rm_escape(char *s, size_t *lenp)
{
    register char *p, *q;
    char *t;

    q = p = s;

    while (*p) {
	if (*p == '\\') {
	    int ch = *++p;
	    switch (ch) {
	    case 'n':
		p++;
		*q++ = '\n';
		break;
	    case 't':
		p++;
		*q++ = '\t';
		break;
	    case 'f':
		p++;
		*q++ = '\f';
		break;
	    case 'b':
		p++;
		*q++ = '\b';
		break;
	    case 'r':
		p++;
		*q++ = '\r';
		break;
	    case 'a':
		p++;
		*q++ = '\07';
		break;
	    case 'v':
		p++;
		*q++ = '\013';
		break;
	    case '\\':
		p++;
		*q++ = '\\';
		break;
	    case '\"':
		p++;
		*q++ = '\"';
		break;
	    case '0':
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
	    case '6':
	    case '7':
		t = p;
		*q++ = (char) octal(&t);
		p = t;
		break;
	    case 'x':
		if (ishex(*(UChar *) (p + 1))) {
		    t = p + 1;
		    *q++ = (char) hex(&t);
		    p = t;
		    break;
		} else {
		    goto not_escape;
		}
	    case '\0':
		*q++ = '\\';
		break;
	      not_escape:
	    default:
		*q++ = '\\';
		*q++ = *p++;
		break;
	    }

	} else
	    *q++ = *p++;
    }

    *q = 0;
    if (lenp != 0)
	*lenp = (unsigned) (q - s);
    return s;
}
Пример #9
0
void MocParser::loadStringData(char *&stringdata)
{
    stringdata = 0;
    QVarLengthArray<char, 1024> array;

    while (!input->atEnd()) {
        QByteArray line = readLine();
        if (line == "};\n") {
            // end of data
            stringdata = new char[array.count()];
            memcpy(stringdata, array.data(), array.count() * sizeof(*stringdata));
            return;
        }

        int start = line.indexOf('"');
        if (start == -1)
            parseError();

        int len = line.length() - 1;
        line.truncate(len);     // drop ending \n
        if (line.at(len - 1) != '"')
            parseError();

        --len;
        ++start;
        for ( ; start < len; ++start)
            if (line.at(start) == '\\') {
                // parse escaped sequence
                ++start;
                if (start == len)
                    parseError();

                QChar c(QLatin1Char(line.at(start)));
                if (!c.isDigit()) {
                    switch (c.toLatin1()) {
                    case 'a':
                        array.append('\a');
                        break;
                    case 'b':
                        array.append('\b');
                        break;
                    case 'f':
                        array.append('\f');
                        break;
                    case 'n':
                        array.append('\n');
                        break;
                    case 'r':
                        array.append('\r');
                        break;
                    case 't':
                        array.append('\t');
                        break;
                    case 'v':
                        array.append('\v');
                        break;
                    case '\\':
                    case '?':
                    case '\'':
                    case '"':
                        array.append(c.toLatin1());
                        break;

                    case 'x':
                        if (start + 2 <= len)
                            parseError();
                        array.append(char(line.mid(start + 1, 2).toInt(0, 16)));
                        break;

                    default:
                        array.append(c.toLatin1());
                        fprintf(stderr, PROGRAMNAME ": warning: invalid escape sequence '\\%c' found in input",
                                c.toLatin1());
                    }
                } else {
                    // octal
                    QRegExp octal(QLatin1String("([0-7]+)"));
                    if (octal.indexIn(QLatin1String(line), start) == -1)
                        parseError();
                    array.append(char(octal.cap(1).toInt(0, 8)));
                }
            } else {
                array.append(line.at(start));
            }
    }

    parseError();
}
Пример #10
0
int
cli_untar(const char *dir, int desc, unsigned int posix, cli_ctx *ctx)
{
	int size = 0, ret, fout=-1;
	int in_block = 0;
	unsigned int files = 0;
	char fullname[NAME_MAX + 1];

	cli_dbgmsg("In untar(%s, %d)\n", dir, desc);

	for(;;) {
		char block[BLOCKSIZE];
		const int nread = cli_readn(desc, block, (unsigned int)sizeof(block));

		if(!in_block && nread == 0)
			break;

		if(nread < 0) {
			if(fout>=0)
				close(fout);
			cli_errmsg("cli_untar: block read error\n");
			return CL_EREAD;
		}

		if(!in_block) {
			char type;
			int directory, skipEntry = 0;
			char magic[7], name[101], osize[13];

			if(fout>=0) {
				lseek(fout, 0, SEEK_SET);
				ret = cli_magic_scandesc(fout, ctx);
				close(fout);
				if (!ctx->engine->keeptmp)
					if (cli_unlink(fullname)) return CL_EUNLINK;
				if (ret==CL_VIRUS)
					return CL_VIRUS;
				fout = -1;
			}

			if(block[0] == '\0')	/* We're done */
				break;
			if((ret=cli_checklimits("cli_untar", ctx, 0, 0, 0))!=CL_CLEAN)
				return ret;

			/* Notice assumption that BLOCKSIZE > 262 */
			if(posix) {
				strncpy(magic, block+257, 5);
				magic[5] = '\0';
				if(strcmp(magic, "ustar") != 0) {
					cli_dbgmsg("cli_untar: Incorrect magic string '%s' in tar header\n", magic);
					return CL_EFORMAT;
				}
			}

			type = block[156];

			switch(type) {
				default:
					cli_dbgmsg("cli_untar: unknown type flag %c\n", type);
				case '0':	/* plain file */
				case '\0':	/* plain file */
				case '7':	/* contiguous file */
				case 'M':	/* continuation of a file from another volume; might as well scan it. */
					files++;
					directory = 0;
					break;
				case '1':	/* Link to already archived file */
				case '5':	/* directory */
				case '2':	/* sym link */
				case '3':	/* char device */
				case '4':	/* block device */
				case '6':	/* fifo special */
				case 'V':	/* Volume header */
					directory = 1;
					break;
				case 'K':
				case 'L':
					/* GNU extension - ././@LongLink
					 * Discard the blocks with the extended filename,
					 * the last header will contain parts of it anyway
					 */
				case 'N': 	/* Old GNU format way of storing long filenames. */
				case 'A':	/* Solaris ACL */
				case 'E':	/* Solaris Extended attribute s*/
				case 'I':	/* Inode only */
				case 'g':	/* Global extended header */
				case 'x': 	/* Extended attributes */
				case 'X':	/* Extended attributes (POSIX) */
					directory = 0;
					skipEntry = 1;
					break;
			}

			if(directory) {
				in_block = 0;
				continue;
			}

			strncpy(osize, block+124, 12);
			osize[12] = '\0';
			size = octal(osize);
			if(size < 0) {
				cli_dbgmsg("cli_untar: Invalid size in tar header\n");
				skipEntry++;
			} else {
				cli_dbgmsg("cli_untar: size = %d\n", size);
				if((ret=cli_checklimits("cli_untar", ctx, size, 0, 0))!=CL_CLEAN)
					skipEntry++;
			}

			if(skipEntry) {
				const int nskip = (size % BLOCKSIZE || !size) ? size + BLOCKSIZE - (size % BLOCKSIZE) : size;
				
				if(nskip < 0) {
					cli_dbgmsg("cli_untar: got nagative skip size, giving up\n");
					return CL_CLEAN;
				}
				cli_dbgmsg("cli_untar: skipping entry\n");
				lseek(desc, nskip, SEEK_CUR);
				continue;
			}

			strncpy(name, block, 100);
			name[100] = '\0';
			if(cli_matchmeta(ctx, name, size, size, 0, files, 0, NULL) == CL_VIRUS)
			    return CL_VIRUS;

			snprintf(fullname, sizeof(fullname)-1, "%s"PATHSEP"tar%02u", dir, files);
			fullname[sizeof(fullname)-1] = '\0';
			fout = open(fullname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);

			if(fout < 0) {
				char err[128];
				cli_errmsg("cli_untar: Can't create temporary file %s: %s\n", fullname, cli_strerror(errno, err, sizeof(err)));
				return CL_ETMPFILE;
			}

			cli_dbgmsg("cli_untar: extracting to %s\n", fullname);

			in_block = 1;
		} else { /* write or continue writing file contents */
			const int nbytes = size>512? 512:size;
			const int nwritten = (int)write(fout, block, (size_t)nbytes);

			if(nwritten != nbytes) {
				cli_errmsg("cli_untar: only wrote %d bytes to file %s (out of disc space?)\n",
					nwritten, fullname);
				close(fout);
				return CL_EWRITE;
			}
			size -= nbytes;
		}
		if (size == 0)
			in_block = 0;
        }	
	if(fout>=0) {
		lseek(fout, 0, SEEK_SET);
		ret = cli_magic_scandesc(fout, ctx);
		close(fout);
		if (!ctx->engine->keeptmp)
			if (cli_unlink(fullname)) return CL_EUNLINK;
		if (ret==CL_VIRUS)
			return CL_VIRUS;
	}
	return CL_CLEAN;
}
Пример #11
0
int
cli_untar(const char *dir, int desc, unsigned int posix)
{
	int size = 0;
	int in_block = 0;
	char fullname[NAME_MAX + 1];
	FILE *outfile = NULL;

	cli_dbgmsg("In untar(%s, %d)\n", dir ? dir : "", desc);

	for(;;) {
		char block[BLOCKSIZE];
		const int nread = cli_readn(desc, block, (unsigned int)sizeof(block));

		if(!in_block && nread == 0)
			break;

		if(nread < 0) {
			if(outfile)
				fclose(outfile);
			cli_errmsg("cli_untar: block read error\n");
			return CL_EIO;
		}

		if(!in_block) {
			char type;
			const char *suffix;
			size_t suffixLen = 0;
			int fd, directory;
			char magic[7], name[101], osize[13];

			if(outfile) {
				if(fclose(outfile)) {
					cli_errmsg("cli_untar: cannot close file %s\n",
					    fullname);
					return CL_EIO;
				}
				outfile = (FILE*)0;
			}

			if(block[0] == '\0')	/* We're done */
				break;

			/* Notice assumption that BLOCKSIZE > 262 */
			if(posix) {
				strncpy(magic, block+257, 5);
				magic[5] = '\0';
				if(strcmp(magic, "ustar") != 0) {
					cli_dbgmsg("Incorrect magic string '%s' in tar header\n", magic);
					return CL_EFORMAT;
				}
			}

			type = block[156];

			/*
			 * Extra types from [email protected]
			 */
			switch(type) {
				case '0':	/* plain file */
				case '\0':	/* plain file */
				case '7':	/* contiguous file */
					directory = 0;
					break;
				case '1':	/* Link to already archived file */
				case '5':	/* directory */
				case '2':	/* sym link */
				case '3':	/* char device */
				case '4':	/* block device */
				case '6':	/* fifo special */
					directory = 1;
					break;
				case 'L':	/* GNU extension - ././@LongLink */
					cli_errmsg("cli_untar: only standard TAR files are currently supported\n", type);
					return CL_EFORMAT;
				default:
					/*cli_errmsg("cli_untar: unknown type flag %c\n", type);
					return CL_EFORMAT;*/
					/*
					 * It isn't really a tar file
					 */
					cli_dbgmsg("cli_untar: unknown type flag %c\n", type);
					/*
					 * We don't know that it's clean at all,
					 * it would be better to have a
					 * CL_CONTINUE return value since it
					 * may be a different format
					 */
					return CL_CLEAN;
			}

			if(directory) {
				in_block = 0;
				continue;
			}

			strncpy(name, block, 100);
			name[100] = '\0';

			/*
			 * see also fileblobSetFilename()
			 * TODO: check if the suffix needs to be put back
			 */
			sanitiseName(name);
			suffix = strrchr(name, '.');
			if(suffix == NULL)
				suffix = "";
			else {
				suffixLen = strlen(suffix);
				if(suffixLen > 4) {
					/* Found a full stop which isn't a suffix */
					suffix = "";
					suffixLen = 0;
				}
			}
			snprintf(fullname, sizeof(fullname) - 1 - suffixLen, "%s/%.*sXXXXXX", dir,
				(int)(sizeof(fullname) - 9 - suffixLen - strlen(dir)), name);
#if    defined(C_LINUX) || defined(C_BSD) || defined(HAVE_MKSTEMP) || defined(C_SOLARIS) || defined(C_CYGWIN) || defined(C_KFREEBSD_GNU)
			fd = mkstemp(fullname);
#else
			(void)mktemp(fullname);
			fd = open(fullname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
#endif

			if(fd < 0) {
				cli_errmsg("Can't create temporary file %s: %s\n", fullname, strerror(errno));
				cli_dbgmsg("%lu %d %d\n", suffixLen, sizeof(fullname), strlen(fullname));
				return CL_ETMPFILE;
			}

			cli_dbgmsg("cli_untar: extracting %s\n", fullname);

			in_block = 1;
			if((outfile = fdopen(fd, "wb")) == NULL) {
				cli_errmsg("cli_untar: cannot create file %s\n",
				    fullname);
				close(fd);
				return CL_ETMPFILE;
			}

			strncpy(osize, block+124, 12);
			osize[12] = '\0';
			size = octal(osize);
			if(size < 0) {
				cli_errmsg("Invalid size in tar header\n");
				if(outfile)
					fclose(outfile);
				return CL_EFORMAT;
			}
			cli_dbgmsg("cli_untar: size = %d\n", size);
		} else { /* write or continue writing file contents */
			const int nbytes = size>512? 512:size;
			const int nwritten = fwrite(block, 1, (size_t)nbytes, outfile);

			if(nwritten != nbytes) {
				cli_errmsg("cli_untar: only wrote %d bytes to file %s (out of disk space?)\n",
					nwritten, fullname);
				if(outfile)
					fclose(outfile);
				return CL_EIO;
			}
			size -= nbytes;
		}
		if (size == 0)
			in_block = 0;
	}
	if(outfile)
		return fclose(outfile);

	return 0;
}
Пример #12
0
int
cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx)
{
	int size = 0, ret, fout=-1;
	int in_block = 0;
	int last_header_bad = 0;
	int limitnear = 0;
	unsigned int files = 0;
	char fullname[NAME_MAX + 1];
	size_t pos = 0;
	size_t currsize = 0;
        char zero[BLOCKSIZE];
	unsigned int num_viruses = 0; 

	cli_dbgmsg("In untar(%s)\n", dir);
        memset(zero, 0, sizeof(zero));

	for(;;) {
	        const char *block;
		size_t nread;

		block = fmap_need_off_once_len(*ctx->fmap, pos, BLOCKSIZE, &nread); 
		cli_dbgmsg("cli_untar: pos = %lu\n", (unsigned long)pos);

		if(!in_block && !nread)
			break;

                if (!nread)
                    block = zero;

		if(!block) {
			if(fout>=0)
				close(fout);
			cli_errmsg("cli_untar: block read error\n");
			return CL_EREAD;
		}
		pos += nread;

		if(!in_block) {
			char type;
			int directory, skipEntry = 0;
			int checksum = -1;
			char magic[7], name[101], osize[TARSIZELEN + 1];
			currsize = 0;

			if(fout>=0) {
				lseek(fout, 0, SEEK_SET);
				ret = cli_magic_scandesc(fout, ctx);
				close(fout);
				if (!ctx->engine->keeptmp)
					if (cli_unlink(fullname)) return CL_EUNLINK;
				if (ret==CL_VIRUS) {
				    if (!SCAN_ALL)
					return CL_VIRUS;
				    else
					num_viruses++;
				}
				fout = -1;
			}

			if(block[0] == '\0')	/* We're done */
				break;
			if((ret=cli_checklimits("cli_untar", ctx, 0, 0, 0))!=CL_CLEAN)
				return ret;

			checksum = getchecksum(block);
			cli_dbgmsg("cli_untar: Candidate checksum = %d, [%o in octal]\n", checksum, checksum);
			if(testchecksum(block, checksum) != 0) {
				// If checksum is bad, dump and look for next header block
				cli_dbgmsg("cli_untar: Invalid checksum in tar header. Skip to next...\n");
				if (last_header_bad == 0) {
					last_header_bad++;
					cli_dbgmsg("cli_untar: Invalid checksum found inside archive!\n");
				}
				continue;
			} else {
				last_header_bad = 0;
				cli_dbgmsg("cli_untar: Checksum %d is valid.\n", checksum);
			}

			/* Notice assumption that BLOCKSIZE > 262 */
			if(posix) {
				strncpy(magic, block+257, 5);
				magic[5] = '\0';
				if(strcmp(magic, "ustar") != 0) {
					cli_dbgmsg("cli_untar: Incorrect magic string '%s' in tar header\n", magic);
					return CL_EFORMAT;
				}
			}

			type = block[TARFILETYPEOFFSET];

			switch(type) {
				default:
					cli_dbgmsg("cli_untar: unknown type flag %c\n", type);
				case '0':	/* plain file */
				case '\0':	/* plain file */
				case '7':	/* contiguous file */
				case 'M':	/* continuation of a file from another volume; might as well scan it. */
					files++;
					directory = 0;
					break;
				case '1':	/* Link to already archived file */
				case '5':	/* directory */
				case '2':	/* sym link */
				case '3':	/* char device */
				case '4':	/* block device */
				case '6':	/* fifo special */
				case 'V':	/* Volume header */
					directory = 1;
					break;
				case 'K':
				case 'L':
					/* GNU extension - ././@LongLink
					 * Discard the blocks with the extended filename,
					 * the last header will contain parts of it anyway
					 */
				case 'N': 	/* Old GNU format way of storing long filenames. */
				case 'A':	/* Solaris ACL */
				case 'E':	/* Solaris Extended attribute s*/
				case 'I':	/* Inode only */
				case 'g':	/* Global extended header */
				case 'x': 	/* Extended attributes */
				case 'X':	/* Extended attributes (POSIX) */
					directory = 0;
					skipEntry = 1;
					break;
			}

			if(directory) {
				in_block = 0;
				continue;
			}

			strncpy(osize, block+TARSIZEOFFSET, TARSIZELEN);
			osize[TARSIZELEN] = '\0';
			size = octal(osize);
			if(size < 0) {
				cli_dbgmsg("cli_untar: Invalid size in tar header\n");
				skipEntry++;
			} else {
				cli_dbgmsg("cli_untar: size = %d\n", size);
				ret = cli_checklimits("cli_untar", ctx, size, 0, 0);
				switch(ret) {
					case CL_EMAXFILES: // Scan no more files 
						skipEntry++;
						limitnear = 0;
						break;
					case CL_EMAXSIZE: // Either single file limit or total byte limit would be exceeded
						cli_dbgmsg("cli_untar: would exceed limit, will try up to max");
						limitnear = 1;
						break;
					default: // Ok based on reported content size
						limitnear = 0;
						break;
				}
			}

			if(skipEntry) {
				const int nskip = (size % BLOCKSIZE || !size) ? size + BLOCKSIZE - (size % BLOCKSIZE) : size;

				if(nskip < 0) {
					cli_dbgmsg("cli_untar: got negative skip size, giving up\n");
					return CL_CLEAN;
				}
				cli_dbgmsg("cli_untar: skipping entry\n");
				pos += nskip;
				continue;
			}

			strncpy(name, block, 100);
			name[100] = '\0';
			if(cli_matchmeta(ctx, name, size, size, 0, files, 0, NULL) == CL_VIRUS) {
			    if (!SCAN_ALL)
				return CL_VIRUS;
			    else
				num_viruses++;
			}

			snprintf(fullname, sizeof(fullname)-1, "%s"PATHSEP"tar%02u", dir, files);
			fullname[sizeof(fullname)-1] = '\0';
			fout = open(fullname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);

			if(fout < 0) {
				char err[128];
				cli_errmsg("cli_untar: Can't create temporary file %s: %s\n", fullname, cli_strerror(errno, err, sizeof(err)));
				return CL_ETMPFILE;
			}

			cli_dbgmsg("cli_untar: extracting to %s\n", fullname);

			in_block = 1;
		} else { /* write or continue writing file contents */
                        int nbytes, nwritten;
                        int skipwrite = 0;
                        char err[128];

			nbytes = size>512? 512:size;
                        if (nread && nread < (size_t)nbytes)
                            nbytes = nread;

			if (limitnear > 0) {
				currsize += nbytes;
				cli_dbgmsg("cli_untar: Approaching limit...\n");
				if (cli_checklimits("cli_untar", ctx, (unsigned long)currsize, 0, 0) != CL_SUCCESS) {
					// Limit would be exceeded by this file, suppress writing beyond limit
					// Need to keep reading to get to end of file chunk
					skipwrite++;
				}
			}

			if (skipwrite == 0) {
				nwritten = (int)cli_writen(fout, block, (size_t)nbytes);

				if(nwritten != nbytes) {
					cli_errmsg("cli_untar: only wrote %d bytes to file %s (out of disc space?): %s\n",
						nwritten, fullname, cli_strerror(errno, err, sizeof(err)));
					close(fout);
					return CL_EWRITE;
				}
			}
			size -= nbytes;
			if ((size != 0) && (nread == 0)) {
				// Truncated tar file, so end file content like tar behavior
				cli_dbgmsg("cli_untar: No bytes read! Forcing end of file content.\n");
				size = 0;
			}
		}
		if (size == 0)
			in_block = 0;
        }
	if(fout>=0) {
		lseek(fout, 0, SEEK_SET);
		ret = cli_magic_scandesc(fout, ctx);
		close(fout);
		if (!ctx->engine->keeptmp)
			if (cli_unlink(fullname)) return CL_EUNLINK;
		if (ret==CL_VIRUS)
			return CL_VIRUS;
	}
	if (num_viruses)
	    return CL_VIRUS;
	return CL_CLEAN;
}
Пример #13
0
int cwt_vsnprintf(CWT_CHAR *string, size_t length, const CWT_CHAR *format, va_list args)
{
	struct DATA data;
	CWT_CHAR conv_field[MAX_FIELD];
	double d; /* temporary holder */
	int state;
	int i;

	data.length = length - 1; /* leave room for '\0' */
	data.holder = string;
	data.pf = format;
	data.counter = 0;

	/* sanity check, the string must be > 1 */
	if (length < 1)
		return -1;


	for (; *data.pf && (data.counter < data.length); data.pf++) {
		if ( *data.pf == _T('%') ) { /* we got a magic % cookie */
			conv_flag((CWT_CHAR *)0, &data); /* initialise format flags */

			for (state = 1; *data.pf && state;) {
				switch (*(++data.pf)) {
				case _T('\0'): /* a NULL here ? ? bail out */
            		*data.holder = _T('\0');
					return data.counter;
					break;

				case _T('f'):  /* float, double */
            		STAR_ARGS(&data);
					d = va_arg(args, double);
					floating(&data, d);
					state = 0;
					break;

				case _T('g'):
				case _T('G'):
					STAR_ARGS(&data);
					DEF_PREC(&data);
					d = va_arg(args, double);
					i = log_10(d);

					/* for '%g|%G' ANSI: use f if exponent
					 * is in the range or [-4,p] exclusively
					 * else use %e|%E
					 */
					if (-4 < i && i < data.precision)
						floating(&data, d);
					else
						exponent(&data, d);
					state = 0;
					break;

				case _T('e'):
				case _T('E'):  /* Exponent double */
					STAR_ARGS(&data);
					d = va_arg(args, double);
					exponent(&data, d);
					state = 0;
					break;

				case _T('u'):
				case _T('d'):  /* decimal */
					STAR_ARGS(&data);
					if (data.a_long == FOUND)
						d = va_arg(args, long);
					else
						d = va_arg(args, int);
					decimal(&data, d);
					state = 0;
					break;

				case _T('o'):  /* octal */
					STAR_ARGS(&data);
					if (data.a_long == FOUND)
						d = va_arg(args, long);
					else
						d = va_arg(args, int);
					octal(&data, d);
					state = 0;
					break;

				case _T('x'):
				case _T('X'):  /* hexadecimal */
					STAR_ARGS(&data);
				  	if (data.a_long == FOUND)
				  		d = va_arg(args, long);
				  	else
				  		d = va_arg(args, int);
				  	hexa(&data, d);
				  	state = 0;
				  	break;

				case _T('c'): /* character */
					d = va_arg(args, int);
					PUT_CHAR((CWT_CHAR)d, &data);
					state = 0;
					break;

				case _T('s'):  /* string */
					STAR_ARGS(&data);
					strings(&data, va_arg(args, CWT_CHAR *));
					state = 0;
					break;

				case _T('n'):
					*(va_arg(args, int *)) = data.counter; /* what's the count ? */
				  	state = 0;
				  	break;

				case _T('l'):
					data.a_long = FOUND;
					break;

				case _T('h'):
					break;

				case _T('%'):  /* nothing just % */
					PUT_CHAR(_T('%'), &data);
					state = 0;
					break;

				case _T('#'): case _T(' '): case _T('+'): case _T('*'):
				case _T('-'): case _T('.'): case _T('0'): case _T('1'):
				case _T('2'): case _T('3'): case _T('4'): case _T('5'):
				case _T('6'): case _T('7'): case _T('8'): case _T('9'):
					/* initialize width and precision */
					for (i = 0; isflag(*data.pf); i++, data.pf++)
						if (i < MAX_FIELD - 1)
							conv_field[i] = *data.pf;

					conv_field[i] = _T('\0');
					conv_flag(conv_field, &data);
					data.pf--;   /* went to far go back */
					break;

				default:
					/* is this an error ? maybe bail out */
					state = 0;
					break;
				} /* end switch */